2010-07-25 92 views

回答

87

添加到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; } 
    } 
} 
+12

有没有办法检索设备的友好名称?例如,当我进入我的USB棒的属性时,我看到“金士顿DataTraveler 2.0 USB设备”。 – Robert 2010-07-26 01:13:52

+1

DeviceID和PNPDeviceID有什么区别? – Shimmy 2011-10-04 19:55:30

+1

当我运行上述程序时,我得到我的USB硬盘,我的键盘和鼠标,但我没有拿到我的USB摄像头,我的USB A/D。为什么不显示所有的USB设备? – Curt 2012-07-23 20:43:06

2

您可能会发现this thread有用。这是一个google code project的例子(它P /调用到setupapi.dll)。

+0

你知道为什么ObjectQuery类没有引用,即使我使用System.Management? – Robert 2010-07-25 22:12:33

+0

@Robert你是否添加了对该项目的参考?您可以通过右键单击项目中的引用>添加引用...>搜索并检查System.Management> OK来完成此操作。 – Ernest 2014-03-06 18:17:34

9

要见我感兴趣的设备,我不得不Win32_PnPEntity在阿德尔Hazzah的代码替换Win32_USBHub的基础上, this post。这个工作对我来说:

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

如果你改变了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设备(与您系统上的所有类型相对)

+0

Where子句搜索以USB开头的设备ID会遗漏一些项目。最好迭代“Win32_USBControllerDevice”的依赖项 – 2016-06-03 02:00:21

22

我知道我回答一个老问题,但我只是通过与此相同的锻炼去了,发现了更多的信息,我认为将有助于很多的讨论和帮忙别人谁发现了这个问题并查看现有答案的不足之处。

accepted answer的靠近,并且可以使用Nedko's comment到它被校正。更详细地了解所涉及的WMI类有助于完成此图。

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

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

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

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

在我的申请,我做了以下内容:

  • (可选)所查询Win32_PnPEntity和以后检索存储在密钥值映射的结果(PNPDeviceID为重点)。如果您想稍后进行个别查询,这是可选的。
  • 查询Win32_USBControllerDevice以获取我系统上所有相关设备(包括所有相关设备)的最终USB设备列表,并提取这些设备的PNPDeviceID。根据设备树的顺序,我进一步深入分配设备到根集线器(返回的第一个设备,而不是控制器),并基于parentIdPrefix构建树。通过SetupDi查询返回的设备树枚举的顺序是每个根集线器(为其前端标识控制器),然后是其下的设备迭代,例如,在我的系统上:
    • 根集线器第一控制器的
    • 第二控制器的
    • 根集线器
        下第二控制器根集线器下下第一轮毂第二控制器(具有parentIdPrefix)
        • 第一复合设备的根集线器
        • 第一毂(PNPDeviceID上述轮毂的相匹配P arentIdPrefix;有它自己的ParentIdPrefix)的复合设备的
          • HID设备部分(PNPDeviceID上述复合设备的ParentIDPrefix下第一毂下第二控制器
            • HID设备部分的根集线器匹配)
          • 第二设备该复合设备的
      • 下塞康的根集线器第二毂d控制器
        • 第一下第二毂下第二控制器根集线器下第二控制器根集线器
    • 所查询Win32_USBController
  • 第三集线器设备。这给了我控制器的PNPDeviceIDs的详细信息,这些控制器位于设备树的顶部(这是前一个查询的前辈)。使用前一步导出的树,递归遍历其子项(根集线器)及其子项(其他集线器)及其子项(非集线器设备和组合设备)及其子项等。
    • 通过引用第一步中存储的映射来检索树中每个设备的详细信息。 (任选地,人们可以跳过第一步,和查询Win32_PnPEntity单独使用PNPDeviceId得到该步骤中的信息;可能是一个CPU与存储器权衡确定哪个命令是更好。)

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

+0

如果有一个连接了4个相同的扫描器,例如,如何区分哪个是哪个? – topshot 2016-10-11 15:28:04

+1

@topshot只要连接,PNPDeviceID就是唯一的。没有办法告诉你是否断开连接,然后连接第二个相同的连接。这个ID在其他领域也被交叉引用以希望识别哪个操作被使用。 – 2016-10-11 21:29:30

2

这是一个简单得多的例子,只为寻找可拆卸的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)); 
    } 
} 
+0

也会返回软盘,可能是USB读卡器,可能是Zip,Jazz和Orb驱动器 – 2017-04-12 18:10:40

0

阿德尔Hazzah的answer给工作代码,Daniel Widdis'sNedko's评论提到你需要查询Win32_USBControllerDevice并使用其相关属性,丹尼尔的answer没有给出代码了很多细节。

这里的上述讨论的合成,以提供工作代码,列出了所有连接的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的答案。