【问题标题】:C# USB flash PNPDeviceID different on some systemsC# USB flash PNPDeviceID 在某些系统上不同
【发布时间】:2018-10-04 07:41:47
【问题描述】:

我正在尝试使用此代码获取 USB 闪存驱动器 ID:

ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
foreach (ManagementObject currentObject in theSearcher.Get())
{                    
    Console.WriteLine("PNPDeviceID: " + currentObject["PNPDeviceID"]);                    
}

在大多数计算机上我会得到这样的东西:USBSTOR\DISK&VEN_TQ&PROD_S1&REV_1.10\11100049977&0

但在某些系统上使用相同的 USB 驱动器时,我会得到如下信息: USBSTOR\DISK&VEN_TQ&PROD_S1&REV_1.10\ 6&2D2B8A01&0& 11100049977&0

请注意,部分 6&2D2B8A01&0& 会根据 USB 驱动器插入的端口而变化。

如何在每个系统上获取第一个版本的 ID,无论是否插入了 USB 驱动器端口?

更新 1:使用 Win32_DiskDrive 时,在每台 PC 上都检测到 USB 驱动器。但是在有问题的 PC 上使用 Win32_USBHub 时无法检测到 USB 驱动器。

更新 2:当使用 answer 中的 SystemUSBDrives 类时,在有问题的 PC 上我得到以下输出:

端口 1:

SystemUSBDrives PNPDeviceID: USBSTOR\DISK&VEN_TQ&PROD_S1&REV_1.10\6&2D2B8A01&0&11100049977&0
SystemUSBDrives DeviceID: \\.\PHYSICALDRIVE2
SystemUSBDrives SerialNumber:  
SystemUSBDrives VolumeSerialNumber: D6533504

端口 2:

SystemUSBDrives PNPDeviceID: USBSTOR\DISK&VEN_TQ&PROD_S1&REV_1.10\6&7A722D3&0&11100049977&0
SystemUSBDrives DeviceID: \\.\PHYSICALDRIVE2
SystemUSBDrives SerialNumber:  
SystemUSBDrives VolumeSerialNumber: D6533504

端口 3:

SystemUSBDrives PNPDeviceID: USBSTOR\DISK&VEN_TQ&PROD_S1&REV_1.10\6&32CECE73&0&11100049977&0
SystemUSBDrives DeviceID: \\.\PHYSICALDRIVE2
SystemUSBDrives SerialNumber:  
SystemUSBDrives VolumeSerialNumber: D6533504

在其他计算机上使用它会返回正确的 SystemUSBDrives SerialNumber 值。

【问题讨论】:

  • 那个“数字”被称为ParentIdPrefix 并被添加以确保PNPDeviceId 在系统中是唯一的。设备不需要有序列号。在这种情况下使用DeviceInstanceID。请在此处查看此类:Get serial number of usb storage device(它不只是获取序列号)。该问题与 .Net Core 2.1 有关,但在其他支持 WMI 查询的框架上也是如此。
  • @Jimi 感谢您的回复。我试过了,不幸的是它没有用。请检查问题中的 UPDATE 2。
  • 这可能是一个相当广泛的问题。根据我的经验,有时 USB 序列号是使用错误的编码编写的。插入了一些 Unicode 字符。这可能会导致一些 USB 控制器失效。在某些情况下,会显示 SerialNumber,但会出现乱码。在 Windows 7 中,有一个更新处理了部分问题。作为 Service Pack 1 和累积更新(类似于 Service Pack 2)的一部分。但我当然不确定是否是这种情况。也许,发布一个可以识别 USB 控制器或显示此问题的 PC 中的某些常见硬件的参考。
  • 您也可以使用DeviceIoControl 试一试。它使用不同的方法(至少在读取设备字符串时)。您需要使用CreateFile() 打开设备,将设备名称作为"\\.\F" 传递,其中F 是逻辑磁盘设备ID(或者简单地说,F: 磁盘)。
  • @Jimi 似乎是针对 C++ 的。我想只解析字符串并删除 ParentIdPrefix。假设 ParentIdPrefix 位于 PNPDeviceID 字符串中最后一个 \ char 和第二个 & 字符之间是否安全?

标签: c# windows wmi wmi-query


【解决方案1】:

您可以使用 DriveInfo 获取所有驱动程序信息。

看这里DriveType

 var drivers = DriveInfo.GetDrives() //all Drivers
                    .Where(x => x.DriveType == DriveType.Removable); //Filter Removable Drivers

或者如果您需要 PNPDeviceID

var deviceSearcher =
            new ManagementObjectSearcher("SELECT * FROM Win32_USBHub");
        foreach (var o in deviceSearcher.Get())
        {
            var usbDevice = (ManagementObject)o;
            var pnpDeviceId = usbDevice.Properties["PNPDeviceID"].Value.ToString();
        }

【讨论】:

  • 不幸的是,在您的示例中使用 Win32_USBHub 时,在有问题的计算机上根本没有检测到 USB 驱动器。
【解决方案2】:

我最终从字符串中删除了 ParentIdPrefix,它适用于我的场景:

public static string RemoveParentIdPrefix(string pnpDeviceId)
{
    int iSplit = pnpDeviceId.LastIndexOf("\\", StringComparison.InvariantCulture);
    string part1 = pnpDeviceId.Substring(0, iSplit);
    string part2 = pnpDeviceId.Substring(iSplit);
    int ampersandCount = 0;
    for (int i = part2.Length - 1; i >= 0; i--)
    {
        if (part2[i] == '&')
        {
            ampersandCount++;
        }

        if (ampersandCount == 2)
        {
            part2 = part2.Substring(i + 1);
            break;
        }
    }
    return part1 + "\\" + part2;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 2012-02-03
    • 1970-01-01
    相关资源
    最近更新 更多