如何使用WMI获取USB设备的驱动器号

Fro*_*art 2 c# wmi

我需要跟踪C#应用程序中的USB插入和移除事件,因此我根据SO上的其他问题提出了以下想法。

我不能用这种方法

var drives = DriveInfo.GetDrives()
    .Where(drive => drive.IsReady && drive.DriveType == DriveType.Removable).ToList();
Run Code Online (Sandbox Code Playgroud)

因为当您需要区分已连接和已断开连接的设备时,这可能会带来很多麻烦(新设备的驱动器号和名称可以与先前缓存的驱动器号和名称相同)。

因此,我决定使用WMI解决此问题,但是我发现无法通过Win32_USBHub类获取指定USB设备的驱动器号。然后我以为我可以执行这样的另一个查询

foreach (ManagementObject device in new ManagementObjectSearcher(@"SELECT * FROM Win32_USBHub").Get())
{
    string deviceID = (string)device.GetPropertyValue("DeviceID");

    Console.WriteLine("{0}", deviceID);

    string query = string.Format("SELECT * FROM Win32_LogicalDisk WHERE DeviceID='{0}'", deviceID);
    foreach (ManagementObject o in new ManagementObjectSearcher(query).Get())
    {
        string name = (string)o.GetPropertyValue("Name");
        Console.WriteLine("{0}", name);
    }

    Console.WriteLine("==================================");
}
Run Code Online (Sandbox Code Playgroud)

但它根本不起作用-每当我尝试执行与Win32_LogicalDisk表兼容的查询时,都会收到“无效查询”的异常。

为什么?我究竟做错了什么?我该如何解决?也许有更好的方法来解决这个问题?

提前致谢。

小智 6

因为对象的deviceID包含需要转义的字符(反斜杠),所以您将获得异常。使用简单替换,您不应获得例外。

string query = string.Format("SELECT * FROM Win32_LogicalDisk WHERE DeviceID='{0}'", deviceID.Replace(@"\", @"\\"));
Run Code Online (Sandbox Code Playgroud)

但是,从WMI获取USB驱动器盘符有点复杂。您需要完成一些课程,如@MSalters在其评论中发布的链接所述:Win32_DiskDrive-> Win32_DiskDriveToDiskPartition -> Win32_DiskPartition -> Win32_LogicalDiskToPartition -> Win32_LogicalDisk.

这里找到的代码的一些修改版本对我有用:

foreach (ManagementObject device in new ManagementObjectSearcher(@"SELECT * FROM Win32_DiskDrive WHERE InterfaceType LIKE 'USB%'").Get())
{
    Console.WriteLine((string)device.GetPropertyValue("DeviceID"));
    Console.WriteLine((string)device.GetPropertyValue("PNPDeviceID"));                

    foreach (ManagementObject partition in new ManagementObjectSearcher(
        "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + device.Properties["DeviceID"].Value
        + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get())
    {
        foreach (ManagementObject disk in new ManagementObjectSearcher(
                    "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='"
                        + partition["DeviceID"]
                        + "'} WHERE AssocClass = Win32_LogicalDiskToPartition").Get())
        {
            Console.WriteLine("Drive letter " + disk["Name"]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)