【问题标题】:How can I get VID/PID from USB Flash drives in C#?如何在 C# 中从 USB 闪存驱动器获取 VID/PID?
【发布时间】:2012-04-20 21:59:48
【问题描述】:

我需要检查所有驱动器并查看是否有任何 VID/PID 与特定的匹配,如果匹配,我需要获取该闪存驱动器的驱动器号。 谢谢大家!

【问题讨论】:

    标签: c# usb pid usb-flash-drive


    【解决方案1】:

    WMI 应该能够处理这个...

    您必须添加对 System.Management dll 的引用,并且您需要: “使用 System.Management;”行...请参阅底部的链接以获取屏幕截图,更详尽的解释...

    using System.Management;
    // Get all the disk drives
    
    ManagementObjectSearcher mosDisks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
    
    // Loop through each object (disk) retrieved by WMI
    
    foreach (ManagementObject moDisk in mosDisks.Get())
    
    {
    
        // Add the HDD to the list (use the Model field as the item's caption)
    
        cmbHdd.Items.Add(moDisk["Model"].ToString());
    
    }
    
    
    private void cmbHdd_SelectedIndexChanged(object sender, EventArgs e)
    
    {
    
    // Get all the disk drives from WMI that match the Model name selected in the ComboBox
    
    ManagementObjectSearcher mosDisks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE Model = '" + cmbHdd.SelectedItem + "'");
    
    // Loop through the drives retrieved, although it should normally be only one loop going on here
    
    foreach (ManagementObject moDisk in mosDisks.Get())
    
    {
    
        // Set all the fields to the appropriate values
    
        lblType.Text = "Type: " + moDisk["MediaType"].ToString();
    
        lblModel.Text = "Model: " + moDisk["Model"].ToString();
    
        lblSerial.Text = "Serial: " + moDisk["SerialNumber"].ToString();
    
        lblInterface.Text = "Interface: " + moDisk["InterfaceType"].ToString();
    
        // The capacity in gigabytes is easily calculated 
    
        lblCapacity.Text = "Capacity: " + moDisk["Size"].ToString() + " bytes (" + Math.Round(((((double)Convert.ToDouble(moDisk["Size"]) / 1024) / 1024) / 1024), 2) + " GB)";
    
        lblPartitions.Text = "Partitions: " + moDisk["Partitions"].ToString();
    
        lblSignature.Text = "Signature: " + moDisk["Signature"].ToString();
    
        lblFirmware.Text = "Firmware: " + moDisk["FirmwareRevision"].ToString();
    
        lblCylinders.Text = "Cylinders: " + moDisk["TotalCylinders"].ToString();
    
        lblSectors.Text = "Sectors: " + moDisk["TotalSectors"].ToString();
    
        lblHeads.Text = "Heads: " + moDisk["TotalHeads"].ToString();
    
        lblTracks.Text = "Tracks: " + moDisk["TotalTracks"].ToString();
    
        lblBytesPerSect.Text = "Bytes per Sector: " + moDisk["BytesPerSector"].ToString();
    
        lblSectorsPerTrack.Text = "Sectors per Track: " + moDisk["SectorsPerTrack"].ToString();
    
        lblTracksPerCyl.Text = "Tracks per Cylinder: " + moDisk["TracksPerCylinder"].ToString();
    
        }
    
    }
    

    来自MSDN CIM_DiskDrive 的 win32 类具有以下参数:

    *看起来“DeviceID”就是你想要的……

    class Win32_DiskDrive : CIM_DiskDrive
    {
      uint16   Availability;
      uint32   BytesPerSector;
      uint16   Capabilities[];
      string   CapabilityDescriptions[];
      string   Caption;
      string   CompressionMethod;
      uint32   ConfigManagerErrorCode;
      boolean  ConfigManagerUserConfig;
      string   CreationClassName;
      uint64   DefaultBlockSize;
      string   Description;
      string   DeviceID;
      boolean  ErrorCleared;
      string   ErrorDescription;
      string   ErrorMethodology;
      string   FirmwareRevision;
      uint32   Index;
      datetime InstallDate;
      string   InterfaceType;
      uint32   LastErrorCode;
      string   Manufacturer;
      uint64   MaxBlockSize;
      uint64   MaxMediaSize;
      boolean  MediaLoaded;
      string   MediaType;
      uint64   MinBlockSize;
      string   Model;
      string   Name;
      boolean  NeedsCleaning;
      uint32   NumberOfMediaSupported;
      uint32   Partitions;
      string   PNPDeviceID;
      uint16   PowerManagementCapabilities[];
      boolean  PowerManagementSupported;
      uint32   SCSIBus;
      uint16   SCSILogicalUnit;
      uint16   SCSIPort;
      uint16   SCSITargetId;
      uint32   SectorsPerTrack;
      string   SerialNumber;
      uint32   Signature;
      uint64   Size;
      string   Status;
      uint16   StatusInfo;
      string   SystemCreationClassName;
      string   SystemName;
      uint64   TotalCylinders;
      uint32   TotalHeads;
      uint64   TotalSectors;
      uint64   TotalTracks;
      uint32   TracksPerCylinder;
    };
    

    代码的顶部取自:

    http://www.geekpedia.com/tutorial233_Getting-Disk-Drive-Information-using-WMI-and-Csharp.html

    【讨论】:

      【解决方案2】:
      public static bool GetDriveVidPid(string szDriveName, ref ushort wVID, ref ushort wPID)
      {
         bool bResult = false;
         string szSerialNumberDevice = null;
      
         ManagementObject oLogicalDisk = new ManagementObject("Win32_LogicalDisk.DeviceID='" + szDriveName.TrimEnd('\\') + "'");
         foreach(ManagementObject oDiskPartition in oLogicalDisk.GetRelated("Win32_DiskPartition"))
         {
            foreach(ManagementObject oDiskDrive in oDiskPartition.GetRelated("Win32_DiskDrive"))
            {
               string szPNPDeviceID = oDiskDrive["PNPDeviceID"].ToString();
               if(!szPNPDeviceID.StartsWith("USBSTOR"))
                  throw new Exception(szDriveName + " ist kein USB-Laufwerk.");
      
               string[] aszToken = szPNPDeviceID.Split(new char[] { '\\', '&' });
               szSerialNumberDevice = aszToken[aszToken.Length - 2];
            }
         }
      
         if(null != szSerialNumberDevice)
         {
            ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(@"root\CIMV2", "Select * from Win32_USBHub");
            foreach(ManagementObject oResult in oSearcher.Get())
            {
               object oValue = oResult["DeviceID"];
               if(oValue == null)
                  continue;
      
               string szDeviceID = oValue.ToString();
               string[] aszToken = szDeviceID.Split(new char[] { '\\' });
               if(szSerialNumberDevice != aszToken[aszToken.Length - 1])
                  continue;
      
               int nTemp = szDeviceID.IndexOf(@"VID_");
               if(0 > nTemp)
                  continue;
      
               nTemp += 4;
               wVID = ushort.Parse(szDeviceID.Substring(nTemp, 4), System.Globalization.NumberStyles.AllowHexSpecifier);
      
               nTemp += 4;
               nTemp = szDeviceID.IndexOf(@"PID_", nTemp);
               if(0 > nTemp)
                  continue;
      
               nTemp += 4;
               wPID = ushort.Parse(szDeviceID.Substring(nTemp, 4), System.Globalization.NumberStyles.AllowHexSpecifier);
      
               bResult = true;
               break;
            }
         }
      
         return bResult;
      }
      

      【讨论】:

        【解决方案3】:

        如果您只需要检查设备何时连接,则问题要简单得多。您需要检查DBT_DEVICEARRIVAL 事件。如果您正在创建 Windows 窗体应用程序,这可以通过实现 IMessageFilter 接口并将其传递给 Application 中的 AddMessageFiler 函数来完成。如果您不使用 Forms 应用程序,则需要从 NativeWindow 派生一个类并覆盖 WndProc。记得调用CreateHandle,它会被添加到windows消息队列中。

        一旦您有办法接收DBT_DEVICEARRIVAL,您就需要将其解析出来。 (以下不是用IDE写的,所以没有测试)

        // Constants from from Dbt.h
        const int WM_DEVICECHANGE = 0x219;
        const int DBT_DEVICEARRIVAL = 0x8000; 
        const uint DBT_DEVTYP_DEVICEINTERFACE = 0x05;
        const Guid GUID_DEVINTERFACE_USB_DEVICE = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");
        
        
        bool PreFilterMessage(ref Message m)
        {
            if(m.Msg == case WM_DEVICECHANGE && m.WParam == DBT_DEVICEARRIVAL)
                var broadcast = (DEV_BROADCAST_HDR)Marshal.PtrToStructure(pnt, typeof(DEV_BROADCAST_HDR));
                if(broadcast.dbch_DeviceType == DBT_DEVTYP_DEVICEINTERFACE)
                {
                    var devInterface = (DEV_BROADCAST_DEVICEINTERFACE)Marshal.PtrToStructure(pnt, typeof(DEV_BROADCAST_DEVICEINTERFACE));
                    if(devInterface.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE)
                    {
                        // devInterface.dbcc_name will contain the VID and PID for example:
                        // \\?\USB#Vid_067b&Pid_2517#6&12115ad4&2&1#{GUID}
                        DoSomthingSpecial(devInterface.dbcc_name);
                    }
                }
            }
            return false;
        }
        
        [StructLayout(LayoutKind.Sequential)]
        struct DEV_BROADCAST_HDR {
           public uint dbch_Size;
           public uint dbch_DeviceType;
           public uint dbch_Reserved;
        }
        
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct DEV_BROADCAST_DEVICEINTERFACE
        {
                public int dbcc_size;
                public int dbcc_devicetype;
                public int dbcc_reserved;
                public Guid dbcc_classguid;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst=255)]
                public string dbcc_name;
        }
        

        如果您需要枚举所有已连接的设备,我只建议使用WMI method。如果您想了解如何在没有 WMI 的情况下执行此操作,请查看 Windows Driver Development Kit 中的 USBView 代码,它可能会帮助您入门。

        【讨论】:

        • 这对于 OP 问题来说是更好的解决方案,因为 WMI 完全是矫枉过正。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-12
        • 1970-01-01
        相关资源
        最近更新 更多