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

本文关键字:驱动器 USB 何使用 WMI 获取 | 更新日期: 2023-09-27 18:07:14

我需要从c#应用程序中跟踪USB插入和删除事件,因此我基于so的其他问题提出了以下想法。

我不能用这个方法

var drives = DriveInfo.GetDrives()
    .Where(drive => drive.IsReady && drive.DriveType == DriveType.Removable).ToList();

,因为当您需要区分已连接和未连接的设备时(新设备可以具有与以前缓存的设备相同的驱动器号和名称),它会导致很多麻烦。

所以我决定使用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("==================================");
}

,但它不工作-我得到一个异常"无效查询"每次当我试图执行查询与Win32_LogicalDisk表工作。

为什么?我做错了什么?我该怎么修理它?也许有更好的方法来解决这个问题?

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

您会得到一个异常,因为您的deviceID包含需要转义的字符(反斜杠)。使用简单的替换,你不应该得到异常。

string query = string.Format("SELECT * FROM Win32_LogicalDisk WHERE DeviceID='{0}'", deviceID.Replace(@"'", @"''"));

然而,从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"]);
        }
    }
}

这是michalk对c# 8的回答的重构版本。

我将它与这个问题的答案结合使用,使用windows服务和c#检测USB驱动器插入和移除,相关问题

        static IEnumerable<(string deviceId, string pnpDeviceId, string driveLetter)> SelectDeviceInformation()
        {
            foreach (ManagementObject device in SelectDevices())
            {
                var deviceId = (string)device.GetPropertyValue("DeviceID");
                var pnpDeviceId = (string)device.GetPropertyValue("PNPDeviceID");
                var driveLetter = (string)SelectPartitions(device).SelectMany(SelectDisks).Select(disk => disk["Name"]).Single();
                yield return (deviceId, pnpDeviceId, driveLetter);
            }
            static IEnumerable<ManagementObject> SelectDevices() => new ManagementObjectSearcher(
                    @"SELECT * FROM Win32_DiskDrive WHERE InterfaceType LIKE 'USB%'").Get()
                .Cast<ManagementObject>();
            static IEnumerable<ManagementObject> SelectPartitions(ManagementObject device) => new ManagementObjectSearcher(
                    "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=" +
                    "'" + device.Properties["DeviceID"].Value + "'} " +
                    "WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get()
                .Cast<ManagementObject>();
            static IEnumerable<ManagementObject> SelectDisks(ManagementObject partition) => new ManagementObjectSearcher(
                    "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=" +
                    "'" + partition["DeviceID"] + "'" +
                    "} WHERE AssocClass = Win32_LogicalDiskToPartition").Get()
                .Cast<ManagementObject>();
        }