WMI:如何区分内部“本地磁盘”和“本地磁盘” HDD和外部“本地磁盘”硬盘

发布于 2024-08-22 19:31:52 字数 3217 浏览 3 评论 0原文

背景
我一直在使用 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)
;

Background
I've been using Win32_DiskDrive to find flash memory (usb pens, SD cards, etc.), but after some tests on other computers I noticed that they weren't always discovered. So I am using Win32_LogicalDisk and since it has DriveType I don't have to associate with two classes (e.g. partition) to find first the drives then their drive letters.

The problem is that external harddrives are detected as DriveType 3 (Local Disk) in LogicalDisk and doesn't have 7 (Supports Removable Media) in Capabilities in DiskDrive. So I can't tell the difference between an internal and external drive.

Question
How do I tell the difference between an internal and an external harddrive using LogicalDisk (or DiskDrive if you really have to) or something third.

Alright. The question has been answered!
Here's the code, if anyone is interested.

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.

One more thing!
Call this a dirty hack or whatever, but I commented out this part of MagWmiGetInfoEx (line 298 in magwmi) in order to make it work:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傲影 2024-08-29 19:31:52

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

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

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

I would suggest sticking with WMI. There is a good delphi wrapper available which includes full source to get you started.

A query to get you started is "SELECT * FROM WIN32_DiskDrive" which would return all of the information for all of the disk drives in your system. the PNPDeviceID field should start with USBSTOR for any USB drives. A good resource for what fields come back is the MSDN website. Just translate the objects into queries.

If your going to be calling this from a thread, you may need to add initialize COM (ComInitialize) before making any calls. Before destroying your thread, call ComUnitialialize.

还不是爱你 2024-08-29 19:31:52

您可以测试这个包; SourceForge 中的 GLibWMI 组件库。它是用于 WMI 的包装。包括 CDiskDriveInfo、CDiskPartitionInfo、CUSBControllerInfo 等可以为您提供帮助的组件。

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

问候。

You can test this package; GLibWMI Components Library in SourceForge. It's a wrapper for work with WMI. Include components like CDiskDriveInfo, CDiskPartitionInfo, CUSBControllerInfo,... that can help you.

Additionally all the code is included. You can evaluate it.

Regards.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文