获取已连接USB设备的列表

Rob*_*ert 88 c# usb

如何获取Windows计算机上所有连接的USB设备的列表?

Ade*_*zah 109

为您的项目添加对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; }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法检索设备的友好名称?例如,当我进入我的usb棒的属性时,我看到"金士顿DataTraveler 2.0 USB设备". (14认同)
  • 它应该被查询"Win32_USBControllerDevice"而不是"Win32_USBHub"以便接收所有USB设备的列表.然后使用"Dependent"属性获取设备地址字符串. (6认同)
  • DeviceID 和 PNPDeviceID 有什么区别? (2认同)

Dan*_*dis 37

我知道我正在回答一个老问题,但我刚刚完成了同样的练习,并找到了更多的信息,我认为这将为讨论做出很多贡献,并帮助找到这个问题的任何其他人看到现有答案不足.

接受的答案是接近的,并且可以使用修正Nedko的评论吧.对WMI类的更详细了解有助于完成图片.

Win32_USBHub仅返回USB 集线器.事后看来这很明显,但上面的讨论错过了它.它不包括所有可能的USB设备,只有那些能够(理论上至少)充当其他设备的集线器的设备.它错过了一些不是集线器的设备(尤其是复合设备的部件).

Win32_PnPEntity确实包括所有USB设备和数百个非USB设备. Russel Gantman建议使用WHERE子句搜索Win32_PnPEntity以"USB%"开头的DeviceID来过滤列表是有帮助的,但稍微不完整; 它错过了蓝牙设备,一些打印机/打印服务器以及符合HID标准的鼠标和键盘.我看过"USB \%","USBSTOR \%","USBPRINT \%","BTH \%","SWD \%"和"HID \%". Win32_PnPEntity但是,一旦您拥有来自其他来源的PNPDeviceID,它就是一个很好的"主"参考.

我发现枚举USB设备的最佳方法是查询Win32_USBControllerDevice.虽然它没有提供有关设备的详细信息,但它确实完全枚举了您的USB设备,并为您的PNPDeviceID每个USB设备(包括集线器,非集线器设备和HID兼容设备)提供了一对前提/相关配对.系统.从查询返回的每个Dependent将是USB设备.Antecedent将是它所分配的控制器,其中一个是通过查询返回的USB控制器Win32_USBController.

作为奖励,似乎在引擎盖下,WMI 在响应查询时遍历设备树Win32_USBControllerDevice,因此返回这些结果的顺序可以帮助识别父/子关系.(这没有记录,因此只是一个猜测;使用SetupDi API的CM_Get_Parent(或Child + Sibling)获得明确的结果.)作为SetupDi API的一个选项,似乎Win32_USBHub可以查找下面列出的所有设备在注册表(at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ + PNPDeviceID)中,将有一个参数ParentIdPrefix,该参数将是其子节点的PNPDeviceID中的最后一个字段的前缀,因此这也可以在通配符匹配中用于过滤Win32_PnPEntity查询.

在我的申请中,我做了以下事情:

  • (可选)查询Win32_PnPEntity并将结果存储在键值映射中(以PNPDeviceID作为键),以便以后检索.如果您想稍后进行单独查询,则这是可选的.
  • 查询Win32_USBControllerDeviceUSB设备的我的系统上的最终名单(所有的受养人)和提取这些的PNPDeviceIDs.我根据设备树之后的顺序进一步将设备分配给根集线器(返回的第一个设备,而不是控制器),并基于parentIdPrefix构建了一个树.查询返回的顺序(通过SetupDi匹配设备树枚举)是每个根集线器(Antecedent为其识别控制器),然后是其下的设备迭代,例如,在我的系统上:
    • 第一个控制器的根集线器
    • 第二个控制器的根集线器
      • 第二个控制器的根集线器下的第一个集线器(具有parentIdPrefix)
        • 第一个集线器位于第二个控制器的根集线器下的第一个集线器下(PNPDeviceID匹配集线器的ParentIdPrefix;具有自己的ParentIdPrefix)
          • 复合设备的HID设备部分(PNPDeviceID匹配以上复合设备的ParentIDPrefix)
        • 在第二控制器的根集线器下的第一集线器下的第二设备
          • HID设备是复合设备的一部分
      • 第二个控制器根集线器下的第二个集线器
        • 在第二控制器的根集线器下的第二集线器下的第一设备
      • 第二个控制器根集线器下的第三个集线器
      • 等等
  • 询问Win32_USBController.这给了我控制器的PNPDeviceID的详细信息,这些控制器位于设备树的顶部(这是前一个查询的前提).使用上一步中派生的树,递归迭代其子节点(根集线器)及其子节点(其他集线器)及其子节点(非集线器设备和复合设备)及其子节点等.
    • 通过引用第一步中存储的映射检索树中每个设备的详细信息.(可选地,可以跳过第一步,并Win32_PnPEntity使用PNPDeviceId单独查询以获取此步骤的信息;可能是cpu与内存权衡,确定哪个顺序更好.)

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

  • 如果设备具有内置的序列号,则可以区分设备(这是序列号的目的)。序列号用作PnP“实例ID”。如果设备不包含序列号,则实例ID本质上是从根到设备通过设备树的路径(并包含'&'字符) (3认同)
  • @topshot只要连接,PNPDeviceID就是唯一的。没有办法告诉您是否断开连接,然后再连接另一个相同的连接。该ID在其他区域也被交叉引用,以希望标识使用了哪个操作。 (2认同)

ocr*_*tte 12

为了查看我感兴趣的设备,我根据这篇文章替换Win32_USBHubWin32_PnPEntityAdel 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; }
  }
}
Run Code Online (Sandbox Code Playgroud)


Rus*_*man 6

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

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

所以“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;
}
Run Code Online (Sandbox Code Playgroud)

}

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


Tyd*_*eus 6

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

    }

}
Run Code Online (Sandbox Code Playgroud)

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


Bad*_*ack 5

对于仅寻找可移动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));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 也将返回软盘,可能是USB读卡器,可能的Zip,Jazz和Orb驱动器 (2认同)