How can I correlate logical drives and physical drives using WMI and Delphi?

I have been working for a long time on an application that can read information from Micro, some (most) have not yet managed with some of them, I work with WMI and Delphi. The problem I am facing is that I need to list the units that apply to each HD, for example: HD1 has a C :, D: drive, etc.

Thank you

+3
source share
2 answers

To correlate logical drives and physical drives, you must use the Win32_DiskDrive and Win32_DiskDriveToDiskPartition , Win32_LogicalDiskToPartition ASSOCIATORS classes .

Try this sample.

 {$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. 

It will output something like this

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

Using the MagWMi shell and its single-line function (single-line - slow - but this is not the place where speed is required). I used it to create a list of 2-tier drives.

  • HardDrive 1 → Letter 1, Letter 2
  • HardDrive 2 → Letter 3, Letter 4
  • NetServer 1 → Letter 5, Letter 6
  • NetServer 2 → Letter 7, Letter 8
  • Unrecognized → All other letters

But you must remember that some discs can be used without a letter. Thus, it will give you information about the root directories, but no more. Drive C: can be created on multiple physical drives. And some physical disks can be used without a letter at all.

 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. 
+2
source

Source: https://habr.com/ru/post/988593/


All Articles