如何获得Windows计算机上所有已连接USB设备的列表?
Answers:
为您的项目添加对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设备,仅包括可以(至少在理论上)充当其他设备集线器的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设备(包括集线器,非Hub设备和HID兼容设备)提供一对先行/从属对。系统。查询返回的每个从属都是USB设备。前一个将是分配给它的控制器,是通过查询返回的USB控制器之一Win32_USBController
。
另外,似乎在幕后,WMI 在响应查询时会遍历“ 设备树 ” 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设备的定义列表(所有的受养人)和提取这些的PNPDeviceIDs。我根据设备树的顺序,进一步将设备分配给根集线器(返回的第一个设备,而不是控制器),并基于parentIdPrefix构建了一棵树。查询返回的顺序与通过SetupDi进行的设备树枚举匹配的顺序是每个根集线器(前者为其标识控制器),然后是其下的设备迭代,例如,在我的系统上:
Win32_USBController
。这给了我控制器的PNPDeviceID的详细信息,这些信息位于设备树的顶部(这是上一个查询的前身)。使用上一步中派生的树,递归遍历其子代(根集线器)及其子代(其他集线器)及其子代(非集线器设备和复合设备)及其子代等。
Win32_PnPEntity
在此步骤中使用PNPDeviceId单独查询以获取信息;可能是CPU与内存的折衷决定了哪个顺序更好。)总而言之,Win32USBControllerDevice
从属是系统上USB设备的完整列表(控制器本身除外,控制器是同一查询中的前身),并且通过将这些PNPDeviceId
对与注册表和提到的其他查询中的信息交叉引用,可以构造一张详细的图片。
要查看我感兴趣的设备,基于这篇文章,我已经用Adel Hazzah的代码替换Win32_USBHub
了。这对我有用: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; }
}
}
Adel Hazzah的答案给出了工作代码,Daniel Widdis和Nedko的评论提到您需要查询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的答案。
对于只寻找可移动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));
}
}
如果将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设备(而不是系统上的所有类型)
您可能会发现此线程很有用。这是一个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);
}
}
}
}
object value
做什么的?