如何使用WMI和Delphi相关逻辑驱动器和物理磁盘?

4

我已经在开发一款能够从Micro读取信息的应用程序上工作了很长一段时间,有些(大部分)失败了,仍然缺少一些功能。我正在使用WMI和Delphi进行开发。

我面临的问题是需要列出属于每个硬盘的单位,例如:HD1有C:、D:等驱动器。

谢谢。


1
为什么这被标记为Java? - David Heffernan
1
类似这样的问题,也许是这个:如何获取USB设备的驱动器号? - LU RD
@Andreas 可能是某种软件吧 ;-) - Arioch 'The
2个回答

12
要关联逻辑驱动器和物理磁盘,你需要使用 Win32_DiskDrive 类和 Win32_DiskDriveToDiskPartitionWin32_LogicalDiskToPartitionASSOCIATORS 类。请尝试此示例。
{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;


function ListDrives : string;
var
  FSWbemLocator  : OLEVariant;
  objWMIService  : OLEVariant;
  colDiskDrives  : OLEVariant;
  colLogicalDisks: OLEVariant;
  colPartitions  : OLEVariant;
  objdiskDrive   : OLEVariant;
  objPartition   : OLEVariant;
  objLogicalDisk : OLEVariant;
  oEnumDiskDrive : IEnumvariant;
  oEnumPartition : IEnumvariant;
  oEnumLogical   : IEnumvariant;
  iValue         : LongWord;
  DeviceID       : string;
begin;
  Result:='';
  FSWbemLocator   := CreateOleObject('WbemScripting.SWbemLocator');
  objWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
  colDiskDrives   := objWMIService.ExecQuery('SELECT DeviceID FROM Win32_DiskDrive');
  oEnumDiskDrive  := IUnknown(colDiskDrives._NewEnum) as IEnumVariant;
  while oEnumDiskDrive.Next(1, objdiskDrive, iValue) = 0 do
   begin
      Writeln(Format('DeviceID %s',[string(objdiskDrive.DeviceID)]));
      //Escape the `\` chars in the DeviceID value because the '\' is a reserved character in WMI.
      DeviceID        := StringReplace(objdiskDrive.DeviceID,'\','\\',[rfReplaceAll]); 
      //link the Win32_DiskDrive class with the Win32_DiskDriveToDiskPartition class
      colPartitions   := objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID]));
      oEnumPartition  := IUnknown(colPartitions._NewEnum) as IEnumVariant;
      while oEnumPartition.Next(1, objPartition, iValue) = 0 do
      begin
       if not VarIsNull(objPartition.DeviceID) then
       begin
        Writeln(Format('   Partition %s',[string(objPartition.DeviceID)]));
        //link the Win32_DiskPartition class with theWin32_LogicalDiskToPartition class.
        colLogicalDisks := objWMIService.ExecQuery('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="'+VarToStr(objPartition.DeviceID)+'"} WHERE AssocClass = Win32_LogicalDiskToPartition'); 
        oEnumLogical  := IUnknown(colLogicalDisks._NewEnum) as IEnumVariant;
          while oEnumLogical.Next(1, objLogicalDisk, iValue) = 0 do
          begin
              Writeln(Format('     Logical Disk %s',[string(objLogicalDisk.DeviceID)]));
              objLogicalDisk:=Unassigned;
          end;
       end;
       objPartition:=Unassigned;
      end;
       objdiskDrive:=Unassigned;
   end;
end;

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

这将输出类似以下内容:

DeviceID \\.\PHYSICALDRIVE0
   Partition Disk #0, Partition #0
     Logical Disk F:
DeviceID \\.\PHYSICALDRIVE1
   Partition Disk #1, Partition #0
     Logical Disk C:

RRUZ - 有没有办法发布一个与Lazarus 1.4.0和Freepascal兼容的版本?我阅读了你的RoadToDelphi条目(https://theroadtodelphi.wordpress.com/2010/12/01/accesing-the-wmi-from-pascal-code-delphi-oxygene-freepascal/#Lazarus),但是尽管进行了更改,我只能列出PhysicalDisks。逻辑驱动器的字母等不会显示,因为以下内容返回为空:objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID])); 我真的非常感激。 - Gizmo_the_Great
@RRUZ - 成功了!!你是个天才!!只有一个小问题,就是 while oEnumLogical.Next(1, objLogicalDisk, ivalue) = 0 do 需要改成 while oEnumLogical.Next(1, objLogicalDisk, nil) = 0 do,但多亏了你的文章,我早就解决了这个问题。真的非常感谢! - Gizmo_the_Great

2
使用MagWMi包装器及其一行函数(该一行函数较慢,但速度并非需要的地方)。 我使用它来制作二级磁盘列表。
  • 硬盘1 -> 字母1,字母2
  • 硬盘2 -> 字母3,字母4
  • 网络服务器1 -> 字母5,字母6
  • 网络服务器2 -> 字母7,字母8
  • 无法识别 -> 所有其他字母
但您必须记住,某些磁盘可能没有任何字母。 因此,这将向您提供有关根目录的信息,但不会更多。 C:盘可能被分配到几个物理磁盘上。 而且有些物理磁盘可能根本不带字母。
unit WMI_Helper;

interface

function WMINetDiskName(const disk: string { 'C:' - w/o slash } ): string;
function WMIPhysDiskName(const disk: string { 'C:' - w/o slash } ): string;
function WMIGetVolumeName(const disk: string { 'C:' - w/o slash } ): string;

implementation

uses magwmi, SysUtils, StrUtils, Windows, IOUtils;

function WMIGetProp(const query, param, resultProp: string): string;
begin
  if MagWmiGetOneQ(StringReplace(query, '%s', param, []), resultProp, Result) <= 0
  then
    Result := '';
  Result := Trim(Result);
end;

function WMINetDiskName(const disk: string { 'C:' - w/o slash } ): string;
const
  req = 'select ProviderName from Win32_MappedLogicalDisk where DeviceID = "%s"';
  prop = 'ProviderName';
var
  i: integer;
begin
  Result := WMIGetProp(req, disk, prop);

  If not TPath.IsUNCPath(Result) then
    exit('');

  i := PosEx('\', TPath.GetPathRoot(Result), 3);
  if i <= 0 then
    exit('');

  SetLength(Result, i - 1);
end;

function WMIPhysDiskName(const disk: string { 'C:' - w/o slash } ): string;
const
  resultProp = 'DeviceID';
  reqPart = 'ASSOCIATORS OF {Win32_LogicalDisk.DeviceID="%s"} WHERE ResultClass=Win32_DiskPartition';
  reqDisk = 'ASSOCIATORS OF {Win32_DiskPartition.DeviceID="%s"} WHERE ResultClass=Win32_DiskDrive';
begin
  Result := WMIGetProp(reqPart, disk, resultProp);
  if Result > '' then
    Result := WMIGetProp(reqDisk, Result, resultProp);
end;

function WMIGetVolumeName(const disk: string { 'C:' - w/o slash } ): string;
const
  prop = 'VolumeName';
  reqNet = 'select VolumeName from Win32_MappedLogicalDisk where DeviceID = "%s"';
  reqPhy = 'select VolumeName from Win32_LogicalDisk where DeviceID = "%s"';

begin
  Result := WMIGetProp(IfThen(GetDriveType(PChar(disk)) = DRIVE_REMOTE, reqNet,
    reqPhy), disk, prop);
end;

end.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接