繁体   English   中英

获取已连接 USB 设备的列表

[英]Get List of connected USB Devices

如何获取 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 Hubs 事后看来,这似乎很明显,但上面的讨论忽略了这一点。 它不包括所有可能的 USB 设备,仅包括那些可以(至少在理论上)充当其他设备集线器的设备。 它错过了一些不是集线器的设备(特别是复合设备的一部分)。

Win32_PnPEntity确实包括所有 USB 设备,以及数百个非 USB 设备。 Russel Gantman 的建议使用 WHERE 子句搜索Win32_PnPEntity以查找以“USB%”开头的 DeviceID 来过滤列表是有帮助的,但有点不完整; 它缺少蓝牙设备、一些打印机/打印服务器以及符合 HID 标准的鼠标和键盘。 我见过“USB\\%”、“USBSTOR\\%”、“USBPRINT\\%”、“BTH\\%”、“SWD\\%”和“HID\\%”。 然而,一旦您拥有来自其他来源的 PNPDeviceID, Win32_PnPEntity是一个很好的“主”参考,用于查找信息。

我发现枚举 USB 设备的最佳方法是查询Win32_USBControllerDevice 虽然它并没有提供详细信息的设备,它不完全列举您的USB设备,并为您的先行/家属对PNPDeviceID S表示每个USB设备(包括集线器,非中心设备和HID兼容设备)上你的系统。 从查询返回的每个 Dependent 将是一个 USB 设备。 Antecedent 将是它分配给的控制器,通过查询Win32_USBController返回的 USB 控制器Win32_USBController

作为奖励,似乎在Win32_USBControllerDevice ,WMI 在响应Win32_USBControllerDevice查询时会Win32_USBControllerDevice 设备树,因此返回这些结果的顺序可以帮助识别父/子关系。 (这不是记录,因此只是一种猜测;使用的SetupDi API的CM_Get_Parent (或儿童+ 同级)的最终结果),作为一个选项的SetupDi API,它看起来,下面列出的所有设备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 Device 部分
      • 第二个控制器的根集线器下的第二个集线器
        • 第二个控制器的根集线器下的第二个集线器下的第一个设备
      • 第二个控制器的根集线器下的第三个集线器
      • 等等。
  • Win32_USBController 这为我提供了位于设备树顶部的控制器的 PNPDeviceID 的详细信息(这是上一个查询的前提)。 使用上一步派生的树,递归迭代其子节点(根集线器)及其子节点(其他集线器)及其子节点(非集线器设备和复合设备)及其子节点等。
    • 通过参考存储在第一步中的地图,检索到我的树中每个设备的详细信息。 (可选地,可以跳过第一步,并使用Win32_PnPEntity单独查询Win32_PnPEntity以获取此步骤的信息;可能是 CPU 与内存权衡决定哪个顺序更好。)

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

看到我感兴趣的设备,我不得不更换Win32_USBHub通过Win32_PnPEntity在阿德尔Hazzah的代码,根据这个帖子 这对我有用:

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; }
  }
}

Adel Hazzah 的回答提供了工作代码, Daniel WiddisNedko 的评论提到您需要查询 Win32_USBControllerDevice 并使用其 Dependent 属性,Daniel 的回答提供了很多没有代码的细节。

这是上述讨论的综合,以提供列出所有连接的 USB 设备的可直接访问的 PNP 设备属性的工作代码:

using System;
using System.Collections.Generic;
using System.Management; // reference required

namespace cSharpUtilities
{
    class UsbBrowser
    {

        public static void PrintUsbDevices()
        {
            IList<ManagementBaseObject> usbDevices = GetUsbDevices();

            foreach (ManagementBaseObject usbDevice in usbDevices)
            {
                Console.WriteLine("----- DEVICE -----");
                foreach (var property in usbDevice.Properties)
                {
                    Console.WriteLine(string.Format("{0}: {1}", property.Name, property.Value));
                }
                Console.WriteLine("------------------");
            }
        }

        public static IList<ManagementBaseObject> GetUsbDevices()
        {
            IList<string> usbDeviceAddresses = LookUpUsbDeviceAddresses();

            List<ManagementBaseObject> usbDevices = new List<ManagementBaseObject>();

            foreach (string usbDeviceAddress in usbDeviceAddresses)
            {
                // query MI for the PNP device info
                // address must be escaped to be used in the query; luckily, the form we extracted previously is already escaped
                ManagementObjectCollection curMoc = QueryMi("Select * from Win32_PnPEntity where PNPDeviceID = " + usbDeviceAddress);
                foreach (ManagementBaseObject device in curMoc)
                {
                    usbDevices.Add(device);
                }
            }

            return usbDevices;
        }

        public static IList<string> LookUpUsbDeviceAddresses()
        {
            // this query gets the addressing information for connected USB devices
            ManagementObjectCollection usbDeviceAddressInfo = QueryMi(@"Select * from Win32_USBControllerDevice");

            List<string> usbDeviceAddresses = new List<string>();

            foreach(var device in usbDeviceAddressInfo)
            {
                string curPnpAddress = (string)device.GetPropertyValue("Dependent");
                // split out the address portion of the data; note that this includes escaped backslashes and quotes
                curPnpAddress = curPnpAddress.Split(new String[] { "DeviceID=" }, 2, StringSplitOptions.None)[1];

                usbDeviceAddresses.Add(curPnpAddress);
            }

            return usbDeviceAddresses;
        }

        // run a query against Windows Management Infrastructure (MI) and return the resulting collection
        public static ManagementObjectCollection QueryMi(string query)
        {
            ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(query);
            ManagementObjectCollection result = managementObjectSearcher.Get();

            managementObjectSearcher.Dispose();
            return result;
        }

    }

}

如果需要,您需要添加异常处理。 如果您想弄清楚设备树等,请咨询 Daniel 的回答。

如果将 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 设备(而不是您系统上的所有类型)

对于只寻找可移动 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));
    }
}

您可能会发现此线程很有用。 这是一个google 代码项目来举例说明这一点(它 P/Invokes into setupapi.dll )。

  lstResult.Clear();
  foreach (ManagementObject drive in new ManagementObjectSearcher("select * from Win32_DiskDrive where InterfaceType='USB'").Get())
  {
       foreach (ManagementObject partition in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + drive["DeviceID"] + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get())
       {
            foreach (ManagementObject disk in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition["DeviceID"] + "'} WHERE AssocClass = Win32_LogicalDiskToPartition").Get())
            {
                  foreach (var item in disk.Properties)
                  {
                       object value = disk.GetPropertyValue(item.Name);
                  }
                  string valor = disk["Name"].ToString();
                  lstResult.Add(valor);
                  }
             }
        }
   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM