7

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

4

3 回答 3

1

WMI should be able to handle this...

You will have to add a Reference to the System.Management dll and you will need to have the: "using System.Management;" line... See Link At Bottom for Screenshots, more thorough explanation...

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();

    }

}

From MSDN the win32 Class for CIM_DiskDrive has the following parameters:

*It looks as if "DeviceID" is what you want...

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;
};

Top Portion oF Code Taken From:

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

于 2012-04-07T21:33:21.413 回答
1
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;
}
于 2013-01-30T16:58:23.093 回答
1

如果您只需要检查设备何时连接,则问题要简单得多。您需要检查DBT_DEVICEARRIVAL事件。如果您正在创建一个 Windows 窗体应用程序,这可以通过实现IMessageFilter接口并将其传递给AddMessageFiler. Application如果您不使用 Forms 应用程序,则需要从NativeWindowWndProc 派生一个类并覆盖它。请记住调用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 方法。如果您想了解如何在没有 WMI 的情况下执行此操作,请查看Windows 驱动程序开发工具包中USBView的代码,它可能会帮助您入门。

于 2012-04-07T21:41:26.057 回答