【问题标题】:WMI: How to distinguish between an internal "local disk" HDD and an external "local disk" HDDWMI:如何区分内部“本地磁盘”硬盘和外部“本地磁盘”硬盘
【发布时间】:2011-01-21 19:30:29
【问题描述】:

背景
我一直在使用 Win32_DiskDrive 来查找闪存(usb 笔、SD 卡等),但在其他计算机上进行了一些测试后,我注意到它们并不总是被发现。所以我使用的是 Win32_LogicalDisk,因为它有 DriveType,所以我不必关联两个类(例如分区)来先找到驱动器,然后再找到它们的驱动器号。

问题是外部硬盘驱动器在 LogicalDisk 中被检测为 DriveType 3(本地磁盘),并且在 DiskDrive 的功能中没有 7(支持可移动媒体)。所以我无法区分内部驱动器和外部驱动器。

问题
如何使用 LogicalDisk(或 DiskDrive,如果你真的需要)或其他方式来区分内部和外部硬盘驱动器。

好的。问题已得到解答!
这是代码,如果有人感兴趣的话。

program GetWMI_USBConnectedInfo;

{$APPTYPE CONSOLE}

uses
  Windows,
  Classes,
  ActiveX,
  Variants,
  SysUtils,
  WbemScripting_TLB, // Using the .pas supplied by the wrapper as it seems to be the XP version of 1.2
  magwmi,
  magsubs1;

function CheckType(Str: string): boolean;
var
  I: Integer;
  Str2: string;
begin
  Result := False;
  for I := 1 to Length(Str) - 1 do if Str[I] = '\' then begin
    Str2 := Copy(Str, 1, I-1);
    Str2 := LowerCase(Str2);
    if (Str2 = 'usbstor') or (Str2 = 'flashmedia') then
      Result := True;
    Break;
  end;
end;

procedure  GetUSBDiskDriveInfo;
var
  I, II, III:  Integer;
  Start, Stop, Freq: Int64;
  instances, instances2, instances3: integer ;
  WmiResults, WmiResults2, WmiResults3: T2DimStrArray ;
  errstr: string ;
begin
  QueryPerformanceFrequency(Freq);
  QueryPerformanceCounter(Start);
  try
    MagWmiGetInfoEx('.', 'root\CIMV2', '', '', 'SELECT * FROM Win32_DiskDrive', WmiResults, instances, errstr);
    for I := 1 to instances do begin
      MagWmiGetInfoEx('.', 'root\CIMV2', '', '', 'ASSOCIATORS OF {Win32_DiskDrive.DeviceID=''' + WmiResults[I, 12] + '''} WHERE AssocClass = Win32_DiskDriveToDiskPartition', WmiResults2, instances2, errstr);
      for II := 1 to instances2 do begin
        MagWmiGetInfoEx('.', 'root\CIMV2', '', '', 'ASSOCIATORS OF {Win32_DiskPartition.DeviceID=''' + WmiResults2[II, 11] + '''} WHERE AssocClass = Win32_LogicalDiskToPartition', WmiResults3, instances3, errstr);
        for III := 1 to instances3 do begin
          if CheckType(WmiResults[I, 32]) or (Pos('7', WmiResults[I, 3])>0) then begin
            Write(WmiResults3[III, 4]);
            Write(WmiResults3[III, 39]);
            Writeln;
          end;
        end;
        WmiResults3 := nil;
      end;
      WmiResults2 := nil;
    end;
    WmiResults := nil;
  except
    Writeln;
    Writeln('error: '+errstr);
  end;
  Writeln;
  QueryPerformanceCounter(Stop);
  if (Freq > 0) then
    Writeln('It took ' + FormatFloat('0.#0', (Stop-Start) / Freq) + ' seconds to complete.');
end;

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

还有一件事!
称之为肮脏的黑客或其他什么,但我注释掉了 MagWmiGetInfoEx 的这一部分(magwmi 中的第 298 行)以使其工作:

//        if Pos ('SELECT', Arg) = 1 then
            wmiObjectSet := wmiServices.ExecQuery (Arg, 'WQL', wbemFlagReturnImmediately, nil)
//        else
//            wmiObjectSet := wmiServices.InstancesOf (Arg, wbemFlagReturnImmediately or
//                                                             wbemQueryFlagShallow, nil)
;

【问题讨论】:

  • 哦,这段代码不只是寻找外置硬盘。它还会检测 USB 笔和闪存卡。
  • 我最初的第二个问题已被删除,因为我不需要它(DBT_DEVICEARRIVAL 和 DBT_DEVICEREMOVECOMPLETE 已经完成了这项工作)。

标签: delphi wmi


【解决方案1】:

我建议坚持使用 WMI。有一个很好的delphi wrapper 可用,其中包括帮助您入门的完整源代码。

帮助您入门的查询是“SELECT * FROM WIN32_DiskDrive”,它将返回系统中所有磁盘驱动器的所有信息。对于任何 USB 驱动器,PNPDeviceID 字段应以 USBSTOR 开头。 MSDN 网站是返回哪些字段的好资源。只需将对象转换为查询即可。

如果您要从线程调用它,您可能需要在进行任何调用之前添加初始化 COM (ComInitialize)。在销毁你的线程之前,调用 ComUnitialize。

【讨论】:

    【解决方案2】:

    你可以测试这个包; GLibWMI Components Library 在 SourceForge 中。它是使用 WMI 的包装器。包括可以帮助您的 CDiskDriveInfo、CDiskPartitionInfo、CUSBControllerInfo 等组件。

    此外,所有代码都包括在内。你可以评价一下。

    问候。

    【讨论】:

      猜你喜欢
      • 2015-01-19
      • 2017-12-07
      • 1970-01-01
      • 2015-05-03
      • 1970-01-01
      • 2017-01-27
      • 2011-06-16
      • 1970-01-01
      • 2011-01-14
      相关资源
      最近更新 更多