I am trying to figure out how to detect if a drive is a mass storage device. I can get the drive letters but cannot figure out how to detect what sort of device it is. I am trying to detect if a Garmin GPS receiver is connected to a PC in mass storage mode.

有帮助吗?

解决方案

You can use the WMI for this task, exist several classes which can help you to determine that information, start with the Win32_USBHub checking for the value Mass Storage Device in the the property Description, also take a look in the Win32_PNPEntity class. If you don't have experience accesing the WMI from Delphi, try using the Wmi delphi code creator

UPDATE

To associate the values returned by the Win32_USBHub or Win32_USBControllerDevice WMI classes with a Disk Drive letter, you must follow the next steps

  1. Query for the Win32_USBControllerDevice class.
  2. Using the DeviceID extracted of the dependent property of each returned instance(record) check the Win32_PnPEntity class loinked to a Win32_DiskDrive using a WQL sentence like so : ASSOCIATORS OF {Win32_PnPEntity.DeviceID="DeviceID"} WHERE ResultClass = Win32_DiskDrive
  3. Now using Win32_DiskDriveToDiskPartition class you can found the link between the Disk Drive and the partition.
  4. Finally using the Win32_LogicalDiskToPartition class you can extract the Drive letter.

Check this sample code

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Types,
  StrUtils,
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

procedure ScanUSBPnpDevices;
const
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator  : OLEVariant;
  objWMIService  : OLEVariant;

  USBControllerDevices: OLEVariant;
  USBControllerDevice : OLEVariant;
  EnumUSBDevice       : IEnumvariant;

  PnPEntities         : OLEVariant;
  PnPEntity           : OLEVariant;
  EnumPnPEntity       : IEnumvariant;

  DiskDrives          : OLEVariant;
  DiskDrive           : OLEVariant;
  EnumDiskDrive       : IEnumvariant;

  DiskPartitions      : OLEVariant;
  DiskPartition       : OLEVariant;
  EnumDiskPartition   : IEnumvariant;

  iValue         : LongWord;
  DeviceID       : string;
  DiskDeviceID   : string;
  DiskPartID     : string;

  StringDynArray : TStringDynArray;
begin;
  FSWbemLocator   := CreateOleObject('WbemScripting.SWbemLocator');
  objWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
  //This will scan all the usb device, you can filter this WQL sentece using any property of this class, to speed-up the process.
  USBControllerDevices := objWMIService.ExecQuery('SELECT Dependent FROM Win32_USBControllerDevice','WQL',wbemFlagForwardOnly);
  EnumUSBDEvice        := IUnknown(USBControllerDevices._NewEnum) as IEnumVariant;
  while EnumUSBDEvice.Next(1, USBControllerDevice, iValue) = 0 do
  begin
    StringDynArray:=SplitString(USBControllerDevice.Dependent, '=');
    DeviceID:=StringDynArray[1];
    Writeln(Format('USB Controller Device Device ID %s',[DeviceID]));
    PnPEntities     := objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_PnPEntity.DeviceID=%s} WHERE ResultClass = Win32_DiskDrive',[DeviceID]),'WQL',wbemFlagForwardOnly);
    EnumPnPEntity   := IUnknown(PnPEntities._NewEnum) as IEnumVariant;
    while EnumPnPEntity.Next(1, PnPEntity, iValue) = 0 do
    begin
      //Escape the `\` chars in the DeviceID value because the '\' is a reserved character in WMI.
      DiskDeviceID   := PnPEntity.DeviceId;
      Writeln(Format('  Disk Drive Device ID %s',[DiskDeviceID]));
      DiskDeviceID   := StringReplace(DiskDeviceID,'\','\\',[rfReplaceAll]);;
      DiskDrives     := objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DiskDeviceID]),'WQL',wbemFlagForwardOnly);
      EnumDiskDrive  := IUnknown(DiskDrives._NewEnum) as IEnumVariant;
      while EnumDiskDrive.Next(1, DiskDrive, iValue) = 0 do
      begin
        DiskPartID:=DiskDrive.deviceID;
        Writeln(Format('    Disk Partition ID %s',[DiskPartID]));
        DiskPartitions:=objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="%s"} WHERE AssocClass = Win32_LogicalDiskToPartition',[DiskPartID]),'WQL',wbemFlagForwardOnly);
        EnumDiskPartition  := IUnknown(DiskPartitions._NewEnum) as IEnumVariant;
        while EnumDiskPartition.Next(1, DiskPartition, iValue) = 0 do
        begin
           Writeln(Format('      Drive Letter %s',[String(DiskPartition.DeviceID)]));
           DiskPartition:=Unassigned;
        end;
        DiskDrive:=Unassigned;
      end;
      PnPEntity:=Unassigned;
    end;
    USBControllerDevice:=Unassigned;
  end;
end;

begin
 try
    CoInitialize(nil);
    try
      ScanUSBPnpDevices;
    finally
      CoUninitialize;
    end;
 except
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
  Readln;
end.

Which will return some thing like this.

USB Controller Device Device ID "USBSTOR\\DISK&VEN_HP&PROD_V100W&REV_1.00\\3S980
62800DD&0"
  Disk Drive Device ID \\.\PHYSICALDRIVE1
    Disk Partition ID Disk #1, Partition #0
      Drive Letter F:
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top