I had been using the code below for a console application in Visual Studio on Windows 8 to return the description and device ID of connected serial devices. I was using a modified version of this in an application I'm creating to automatically detect the COM port of an Arduino. It no longer returns anything since I've done a fresh install with Windows 10. I have a USB to serial AVR programmer that still shows up using this code however. I checked the registry and the Arduino is listed in SERIALCOMM, the Arduino is showing as 'USB Serial Port (COM6)' under 'Ports (COM & LPT)' in Device Manager and I can program the Arduino using the Arduino software. I have no idea why it isn't working any more.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.IO.Ports;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
ManagementScope connectionScope = new ManagementScope();
SelectQuery serialQuery = new SelectQuery("SELECT * FROM Win32_SerialPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(connectionScope, serialQuery);
try
{
foreach (ManagementObject item in searcher.Get())
{
string desc = item["Description"].ToString();
string deviceId = item["DeviceID"].ToString();
Console.WriteLine(desc);
Console.WriteLine(deviceId);
}
}
catch (ManagementException e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
}
}
It might also be relevant that while trying to find a solution I found the following implementation to find port names using MSSerial_PortName and I got an Access Denied error.
using System;
using System.Management;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
try
{
ManagementObjectSearcher MOSearcher = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSSerial_PortName");
foreach (ManagementObject MOject in MOSearcher.Get())
{
Console.WriteLine(MOject["PortName"]);
}
}
catch (ManagementException me)
{
Console.WriteLine("An error occurred while querying for WMI data: " + me.Message);
}
Console.ReadKey();
}
}
}
Ok, I think I see the issue now (I will add a new answer, but won't replace the old in case someone finds the information useful).
Win32_SerialPort
only detects hardware serial ports (e.g. RS232).
Win32_PnPEntity
identifies plug-and-play devices including hardware and virtual serial ports (e.g. COM port created by the FTDI driver).
To use Win32_PnPEntity
to identify a driver requires a little extra work. The following code identifies all COM ports on the system and produces a list of said ports. From this list, you may identify the appropriate COM port number to create your SerialPort object.
// Class to contain the port info.
public class PortInfo
{
public string Name;
public string Description;
}
// Method to prepare the WMI query connection options.
public static ConnectionOptions PrepareOptions ( )
{
ConnectionOptions options = new ConnectionOptions ( );
options . Impersonation = ImpersonationLevel . Impersonate;
options . Authentication = AuthenticationLevel . Default;
options . EnablePrivileges = true;
return options;
}
// Method to prepare WMI query management scope.
public static ManagementScope PrepareScope ( string machineName , ConnectionOptions options , string path )
{
ManagementScope scope = new ManagementScope ( );
scope . Path = new ManagementPath ( @"\\" + machineName + path );
scope . Options = options;
scope . Connect ( );
return scope;
}
// Method to retrieve the list of all COM ports.
public static List<PortInfo> FindComPorts ( )
{
List<PortInfo> portList = new List<PortInfo> ( );
ConnectionOptions options = PrepareOptions ( );
ManagementScope scope = PrepareScope ( Environment . MachineName , options , @"\root\CIMV2" );
// Prepare the query and searcher objects.
ObjectQuery objectQuery = new ObjectQuery ( "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0" );
ManagementObjectSearcher portSearcher = new ManagementObjectSearcher ( scope , objectQuery );
using ( portSearcher )
{
string caption = null;
// Invoke the searcher and search through each management object for a COM port.
foreach ( ManagementObject currentObject in portSearcher . Get ( ) )
{
if ( currentObject != null )
{
object currentObjectCaption = currentObject [ "Caption" ];
if ( currentObjectCaption != null )
{
caption = currentObjectCaption . ToString ( );
if ( caption . Contains ( "(COM" ) )
{
PortInfo portInfo = new PortInfo ( );
portInfo . Name = caption . Substring ( caption . LastIndexOf ( "(COM" ) ) . Replace ( "(" , string . Empty ) . Replace ( ")" , string . Empty );
portInfo . Description = caption;
portList . Add ( portInfo );
}
}
}
}
}
return portList;
}