SerialDevice.GetDeviceSelector()
can be used to answer the specific scenario I had of enumerating serial devices.
DeviceInformationCollection deviceSearchResults = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelector());
But looking at the question of how can the class, subclass, and protocol be used to list the same information, it is unclear.
UsbDevice.GetDeviceClassSelector(new UsbDeviceClass
{
ClassCode = 0x02,
SubclassCode = 0x02,
ProtocolCode = 0x01
});
The code above generates the string
System.Devices.InterfaceClassGuid:="{DEE824EF-729B-4A0E-9C14-B7117D33A817}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND System.DeviceInterface.WinUsb.UsbClass:=2 AND System.DeviceInterface.WinUsb.UsbSubClass:=2 AND System.DeviceInterface.WinUsb.UsbProtocol:=1
There were two reasons this was not working.
The first can be seen when looking at the System.Devices.InterfaceClassGuid
. The value of this property for the serial ports listed was not DEE824EF-729B-4A0E-9C14-B7117D33A817
but 86e0d1e0-8089-11d0-9ce4-08003e301f73
. SerialDevice.GetDeviceSelector()
seems to take this into account as it returns
System.Devices.InterfaceClassGuid:="{86E0D1E0-8089-11D0-9CE4-08003E301F73}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True
The second is when using DeviceInformation.FindAllAsync
to load additional parameters which you would expect to match the values shown in the screenshot in the question, they are actually empty.
The code
private async void List()
{
DeviceInformationCollection deviceSearchResults = await DeviceInformation.FindAllAsync("", new[]
{
"System.Devices.InterfaceClassGuid",
"System.DeviceInterface.Serial.PortName",
"System.DeviceInterface.Serial.UsbProductId",
"System.DeviceInterface.Serial.UsbVendorId",
"System.Devices.CompatibleIds",
"System.Devices.ClassGuid",
"System.DeviceInterface.WinUsb.UsbClass",
"System.DeviceInterface.WinUsb.UsbSubClass",
"System.DeviceInterface.WinUsb.UsbProtocol",
});
foreach (DeviceInformation device in deviceSearchResults)
{
PrintInfo(device);
}
}
private static void PrintInfo(DeviceInformation device)
{
Debug.WriteLine("Device:");
Debug.WriteLine($"\tID: {device.Id}");
Debug.WriteLine($"\tName: {device.Name}");
Debug.WriteLine($"\tIs Enabled: {device.IsEnabled}");
Debug.WriteLine($"\tIs Default: {device.IsDefault}");
Debug.WriteLine($"\tKind: {device.Kind}");
if (device.EnclosureLocation != null)
{
Debug.WriteLine("\tEnclosure Location:");
Debug.WriteLine($"\t\tIn Dock: {device.EnclosureLocation.InDock}");
Debug.WriteLine($"\t\tIn Lid: {device.EnclosureLocation.InLid}");
Debug.WriteLine($"\t\tPanel: {device.EnclosureLocation.Panel}");
Debug.WriteLine($"\t\tRotation Angle In Degrees Clockwise: {device.EnclosureLocation.RotationAngleInDegreesClockwise}");
}
if (device.Pairing != null)
{
Debug.WriteLine("\tPairing Info:");
Debug.WriteLine($"\t\tCan Pair: {device.Pairing.CanPair}");
Debug.WriteLine($"\t\tIs Paired: {device.Pairing.IsPaired}");
Debug.WriteLine($"\t\tProtection Level: {device.Pairing.ProtectionLevel}");
}
Debug.WriteLine("\tProperties:");
foreach ((string key, object value) in device.Properties)
{
Debug.WriteLine($"\t\t{key}: {value}");
}
Debug.WriteLine("");
}
returns the following output showing that additional parameters such as CompatibleIds is empty.
Device:
ID: \\?\USB#VID_2341&PID_0043#9563533333135161B150#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
Name: USB Serial Device (COM3)
Is Enabled: True
Is Default: False
Kind: DeviceInterface
Enclosure Location:
In Dock: False
In Lid: False
Panel: Right
Rotation Angle In Degrees Clockwise: 0
Pairing Info:
Can Pair: False
Is Paired: False
Protection Level: None
Properties:
System.ItemNameDisplay: USB Serial Device (COM3)
System.Devices.DeviceInstanceId: USB\VID_2341&PID_0043\9563533333135161B150
System.Devices.Icon: C:\Windows\System32\DDORes.dll,-2001
System.Devices.GlyphIcon: C:\Windows\System32\DDORes.dll,-3001
System.Devices.InterfaceEnabled: True
System.Devices.IsDefault: False
System.Devices.PhysicalDeviceLocation: System.Byte[]
System.Devices.ContainerId: 57921dd6-46ab-5d6d-a362-0a14d0827375
System.Devices.InterfaceClassGuid: 86e0d1e0-8089-11d0-9ce4-08003e301f73
System.DeviceInterface.Serial.PortName: COM3
System.DeviceInterface.Serial.UsbProductId: 67
System.DeviceInterface.Serial.UsbVendorId: 9025
System.Devices.CompatibleIds:
System.Devices.ClassGuid:
System.DeviceInterface.WinUsb.UsbClass:
System.DeviceInterface.WinUsb.UsbSubClass:
System.DeviceInterface.WinUsb.UsbProtocol:
As a side note, if anyone is here looking to achieve something similar in WPF / other desktop applications, which is the approach I took at the time, it can be achieved in a few ways using WMI.
// If in .NET Core / .NET 5 run
// Install-Package System.Management -Version 5.0.0
// See https://www.nuget.org/packages/System.Management/
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("SELECT * FROM Win32_SerialPort");
foreach (ManagementBaseObject queryObj in searcher.Get())
{
Debug.WriteLine("COM Port");
Debug.WriteLine($"DeviceID: {queryObj["DeviceID"]}");
Debug.WriteLine($"Name: {queryObj["NAME"]}");
Debug.WriteLine($"Description: {queryObj["Description"]}");
Debug.WriteLine($"PNPDeviceID: {queryObj["PNPDeviceID"]}");
Debug.WriteLine("");
}
// If in .NET Core / .NET 5 run
// Install-Package Microsoft.Management.Infrastructure -Version 2.0.0
// See https://www.nuget.org/packages/Microsoft.Management.Infrastructure/
CimSession cimSession = CimSession.Create(null);
IEnumerable<CimInstance> queryInstances =
cimSession.QueryInstances(@"root\cimv2",
"WQL",
@"SELECT * FROM Win32_SerialPort");
foreach (CimInstance cimInstance in queryInstances)
{
Debug.WriteLine("COM Port");
Debug.WriteLine($"DeviceID: {cimInstance.CimInstanceProperties["DeviceID"].Value}");
Debug.WriteLine($"Name: {cimInstance.CimInstanceProperties["NAME"].Value}");
Debug.WriteLine($"Description: {cimInstance.CimInstanceProperties["Description"].Value}");
Debug.WriteLine($"PNPDeviceID: {cimInstance.CimInstanceProperties["PNPDeviceID"].Value}");
Debug.WriteLine("");
}
The issue with the WMI / CIM approach for UWP is that it is not supported, even if the NuGets can be installed. One solution for this could be use desktop bridge to include Win32 code in a UWP app as a background process. See here and here for more information.
A resource that seems to be able to get a lot of information about USBs is USB View. It isn't written in C# but it is open source and is written in C so it might be translatable to C#.
0
device back? – InamoratoFindAllAsync
is aIAsyncOperation
– Lumbricoidstring[] PortNames = SerialPort.GetPortNames();
would provide you with the ports with connected devices. from there you can take the names and get the details of the devices connected. – Kroll