获取连接的USB设备列表

如何获得Windows电脑上所有连接的USB设备的列表?

为您的项目添加对System.Management的引用,然后尝试如下所示:

namespace ConsoleApplication1 { using System; using System.Collections.Generic; using System.Management; // need to add System.Management to your project references. class Program { static void Main(string[] args) { var usbDevices = GetUSBDevices(); foreach (var usbDevice in usbDevices) { Console.WriteLine("Device ID: {0}, PNP Device ID: {1}, Description: {2}", usbDevice.DeviceID, usbDevice.PnpDeviceID, usbDevice.Description); } Console.Read(); } static List<USBDeviceInfo> GetUSBDevices() { List<USBDeviceInfo> devices = new List<USBDeviceInfo>(); ManagementObjectCollection collection; using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_USBHub")) collection = searcher.Get(); foreach (var device in collection) { devices.Add(new USBDeviceInfo( (string)device.GetPropertyValue("DeviceID"), (string)device.GetPropertyValue("PNPDeviceID"), (string)device.GetPropertyValue("Description") )); } collection.Dispose(); return devices; } } class USBDeviceInfo { public USBDeviceInfo(string deviceID, string pnpDeviceID, string description) { this.DeviceID = deviceID; this.PnpDeviceID = pnpDeviceID; this.Description = description; } public string DeviceID { get; private set; } public string PnpDeviceID { get; private set; } public string Description { get; private set; } } } 

我知道我正在回答一个古老的问题,但是我只是经历了这个相同的练习,发现了更多的信息,我认为这将有助于讨论,并帮助其他任何发现这个问题的人,现有的答案不足。

接受的答案是接近的,可以用Nedko的评论来纠正。 对WMI类的更详细的理解有助于完成这个画面。

Win32_USBHub只返回USB 集线器 。 事后看来这似乎很明显,但上面的讨论忽略了它。 它不包括所有可能的USB设备,只有那些可以(至少在理论上)作为附加设备集线器的设备。 它错过了一些不是集线器的设备(尤其是复合设备的一部分)。

Win32_PnPEntity包括所有USB设备,以及数百个非USB设备。 Russel Gantman建议使用WHERE子句搜索以“USB%”开头的DeviceID的Win32_PnPEntity来过滤列表,但是稍微不完整; 它错过了HID兼容的鼠标和键盘。 我相信“USB \%”,“USBSTOR \%”,“USBPRINT \%”和“HID \%”将完全列举所有的可能性,但是由于有更好的选择,所以这可能不需要追求。 然而, Win32_PnPEntity是一个很好的“主”引用来查询信息,一旦你从其他来源拥有PNPDeviceID。

我发现枚举USB设备的最好方法是查询Win32_USBControllerDevice 。 虽然没有提供设备的详细信息,但是它完全枚举了USB设备,并为每个USB设备(包括集线器,非集线器设备和HID兼容设备)提供了PNPDeviceID /从属对PNPDeviceID你的系统。 从查询返回的每个从属将是一个USB设备。 Antecedent将被分配到的控制器,通过查询Win32_USBController返回的USB控制器Win32_USBController

作为奖励,看起来如下,WMI在响应Win32_USBControllerDevice查询时Win32_USBControllerDevice 设备树 ,所以返回这些结果的顺序可以帮助识别父/子关系。 (这没有记录,因此只是一个猜测;使用SetupDi API的CM_Get_Parent (或Child + 兄弟 )来获得明确的结果。)作为SetupDi API的一个选项,对于Win32_USBHub下列出的所有设备Win32_USBHub , (在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID ),并将有一个参数ParentIdPrefix这将是其子的PNPDeviceID的最后一个字段的前缀,所以这也可以用于通配符匹配筛选Win32_PnPEntity查询。

在我的申请中,我做了以下工作:

  • (可选) Win32_PnPEntity并将结果存储在键值映射(以PNPDeviceID作为键)中以供稍后检索。 如果您想稍后进行个别查询,这是可选的。
  • Win32_USBControllerDevice获取我的系统(所有依赖项)上的USB设备的确切列表,并提取这些设备的PNPDeviceID。 根据设备树的顺序,我进一步深入分配设备到根集线器(返回的第一个设备,而不是控制器),并构建了一个基于parentIdPrefix的树。 查询返回的顺序与通过SetupDi进行的设备树枚举相匹配,每个根集线器(Antecedent为其标识控制器),然后是其下的设备迭代,例如在我的系统上:
    • 第一个控制器的根集线器
    • 第二个控制器的根集线器
      • 第二个控制器根集线器下的第一个集线器(有parentIdPrefix)
        • 在第二个控制器的根集线器下的第一个集线器下的第一个复合设备(PNPDeviceID与集线器的ParentIdPrefix匹配;具有它自己的ParentIdPrefix)
          • 组合设备的HID设备部分(PNPDeviceID与上述复合设备的ParentIDPrefix匹配)
        • 第二个控制器根集线器下第一个集线器下的第二个设备
          • HID设备部分的复合设备
      • 第二个控制器根集线器下的第二个集线器
        • 第二个控制器根集线器下第二个集线器下的第一个设备
      • 第二个控制器根集线器下的第三个集线器
      • 等等
  • Win32_USBController 。 这给了我在我的控制器的PNPDeviceID的详细信息在设备树的顶部(这是前一个查询的前奏)。 使用前一步导出的树,递归地遍历其子(根集线器)及其子集(其他集线器)及其子集(非集线器设备和复合设备)及其子集等。
    • 通过引用第一步中存储的映射,检索我的树中每个设备的详细信息。 (或者,可以跳过第一步,使用Win32_PnPEntity单独查询Win32_PnPEntity以获取此步骤的信息;可能是CPU与内存的折衷决定哪个顺序更好。

总之, Win32USBControllerDevice Dependents是一个系统上USB设备的完整列表(除了控制器本身,它们是同一个查询中的前提),并且通过交叉引用这些PNPDeviceId对与来自注册表和其他查询的信息如上所述,可以构建详细的图片。

要查看我感兴趣的设备,我已经用Adel Hazzah代码中的Win32_PnPEntity替换了Win32_PnPEntity 。 这适用于我:

 namespace ConsoleApplication1 { using System; using System.Collections.Generic; using System.Management; // need to add System.Management to your project references. class Program { static void Main(string[] args) { var usbDevices = GetUSBDevices(); foreach (var usbDevice in usbDevices) { Console.WriteLine("Device ID: {0}, PNP Device ID: {1}, Description: {2}", usbDevice.DeviceID, usbDevice.PnpDeviceID, usbDevice.Description); } Console.Read(); } static List<USBDeviceInfo> GetUSBDevices() { List<USBDeviceInfo> devices = new List<USBDeviceInfo>(); ManagementObjectCollection collection; using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity")) collection = searcher.Get(); foreach (var device in collection) { devices.Add(new USBDeviceInfo( (string)device.GetPropertyValue("DeviceID"), (string)device.GetPropertyValue("PNPDeviceID"), (string)device.GetPropertyValue("Description") )); } collection.Dispose(); return devices; } } class USBDeviceInfo { public USBDeviceInfo(string deviceID, string pnpDeviceID, string description) { this.DeviceID = deviceID; this.PnpDeviceID = pnpDeviceID; this.Description = description; } public string DeviceID { get; private set; } public string PnpDeviceID { get; private set; } public string Description { get; private set; } } } 

如果将ManagementObjectSearcher更改为以下内容:

 ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", @"SELECT * FROM Win32_PnPEntity where DeviceID Like ""USB%"""); 

所以“GetUSBDevices()”看起来像这样“

 static List<USBDeviceInfo> GetUSBDevices() { List<USBDeviceInfo> devices = new List<USBDeviceInfo>(); ManagementObjectCollection collection; using (var searcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity where DeviceID Like ""USB%""")) collection = searcher.Get(); foreach (var device in collection) { devices.Add(new USBDeviceInfo( (string)device.GetPropertyValue("DeviceID"), (string)device.GetPropertyValue("PNPDeviceID"), (string)device.GetPropertyValue("Description") )); } collection.Dispose(); return devices; } 

}

您的结果将仅限于USB设备(而不是系统上的所有类型)

你可能会觉得这个线程很有用。 这里是一个例子的谷歌代码项目 (它P /调用setupapi.dll )。

这是一个简单的例子,人们只要找可拆卸的USB驱动器。

using System.IO;

 foreach (DriveInfo drive in DriveInfo.GetDrives()) { if (drive.DriveType == DriveType.Removable) { Console.WriteLine(string.Format("({0}) {1}", drive.Name.Replace("\\",""), drive.VolumeLabel)); } }