我正在尝试动态列出连接到计算机的USB与某个UsbDeviceClass
匹配的USB有关我尝试在设备管理器中列出的USB类的信息如下
理想情况下,它应该能够列出Com
端口,因为我希望列出的设备特别是Arduinos。
DeviceInformationCollection usbDeviceInfoCollection = await DeviceInformation.FindAllAsync(UsbDevice.GetDeviceClassSelector(new UsbDeviceClass()
{
ClassCode = 0x02,
SubclassCode = 0x02,
ProtocolCode = 0x01
}));
Debug.WriteLineIf(usbDeviceInfoCollection.Count == 1, "1 USB device found");
Debug.WriteLineIf(usbDeviceInfoCollection.Count != 1, usbDeviceInfoCollection.Count + " USB devices found");
for (int i = 0; i < usbDeviceInfoCollection.Count; i++)
{
Debug.WriteLine("USB Device " + (i + 1));
Debug.WriteLine("ID: " + usbDeviceInfoCollection[i].Id);
Debug.WriteLine("Name: " + usbDeviceInfoCollection[i].Name);
Debug.WriteLine("Properties: " + usbDeviceInfoCollection[i].Properties);
Debug.WriteLine("");
}
上面的代码显示了我一直在努力实现这一目标,但到目前为止我没有运气。这是因为当程序运行时,如果连接了设备,它将返回0个设备。
我也尝试使用预定义的类UsbDeviceClasses.CdcControl
,但是,这也没有达到我想要的结果。
我很欣赏有关如何正确实现这一目标的任何指导。
此外,由于这是一个UWP项目,我已经包含了以下功能,因此它应该能够检测到我想要的设备。
<DeviceCapability Name="serialcommunication">
<Device Id="any">
<Function Type="name:serialPort"/>
</Device>
</DeviceCapability>
使用DeviceInformation.FindAllAsync()
编写的程序略有变化的Arduino信息输出示例,其中UsbDeviceClass
为jsanalytics。
Device 1354
EnclosureLocation: Windows.Devices.Enumeration.EnclosureLocation
ID: \\?\USB#VID_2341&PID_0243#9543231323835131B172#{86e0d1e0-8089-11d0-9ce4-08003e301f73}
IsDefault: False
IsEnabled: True
Kind: DeviceInterface
Name: Genuino Uno (COM6)
Pairing: Windows.Devices.Enumeration.DeviceInformationPairing
Properties: System.__ComObject
注册表图片
更新,this page有关更具体的USB功能,包括name:cdcControl, classId:02 * *
。但是,我仍然无法通过像这个远程arduino应用程序那样的附加设备进行枚举; Windows Remote Arduino Experience
快速编辑以澄清。我无法连接到设备,我只能枚举02类子类02协议01的设备。可以通过指定VID和PID连接到我的设备,但在当前情况下,这是无视点
答案 0 :(得分:1)
您可以枚举外部USB设备,首先需要在 Package.appxmanifest 文件中添加此权限。
<uap:Capability Name="removableStorage" />
然后在您的应用中编写此代码。
var removableDevices = KnownFolders.RemovableDevices;
var externalDrives = await removableDevices.GetFoldersAsync();
foreach (var item in externalDrives)
{
var name = item.DisplayName;
}
现在有一个刷新列表重新运行代码。
答案 1 :(得分:1)
SerialDevice.GetDeviceSelector()
可用于回答我在枚举串行设备时遇到的特定场景。
DeviceInformationCollection deviceSearchResults = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelector());
但是看看如何使用类、子类和协议来列出相同信息的问题,就不清楚了。
UsbDevice.GetDeviceClassSelector(new UsbDeviceClass
{
ClassCode = 0x02,
SubclassCode = 0x02,
ProtocolCode = 0x01
});
上面的代码生成字符串
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
这不起作用有两个原因。
第一个可以在查看 System.Devices.InterfaceClassGuid
时看到。列出的串行端口的此属性值不是 DEE824EF-729B-4A0E-9C14-B7117D33A817
而是 86e0d1e0-8089-11d0-9ce4-08003e301f73
。 SerialDevice.GetDeviceSelector()
在返回时似乎考虑到了这一点
System.Devices.InterfaceClassGuid:="{86E0D1E0-8089-11D0-9CE4-08003E301F73}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True
第二种情况是,当使用 DeviceInformation.FindAllAsync
加载额外的参数时,您希望这些参数与问题屏幕截图中显示的值相匹配,但它们实际上是空的。
代码
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("");
}
返回以下输出,显示 CompatibleIds 等其他参数为空。
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:
顺便提一下,如果有人想在 WPF/其他桌面应用程序中实现类似的东西,这是我当时采用的方法,可以使用 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("");
}
UWP 的 WMI/CIM 方法的问题在于它不受支持,即使可以安装 NuGet。对此的一种解决方案是使用桌面桥将 Win32 代码作为后台进程包含在 UWP 应用中。有关详细信息,请参阅 here 和 here。
似乎能够获取大量有关 USB 信息的资源是 USB View。它不是用 C# 编写的,但它是开源的并且是用 C 编写的,因此它可能可以翻译成 C#。