Using WMI
This is a simple project to enumerate drives and their serial numbers.
The project is available here on GitHub.
It uses WMI, the only tricky part were the associator queries:
{ query constants }
CPartitionQuery = '''
ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"}
WHERE AssocClass = Win32_DiskDriveToDiskPartition
''';
CDiskQuery = '''
ASSOCIATORS OF {Win32_DiskPartition.DeviceID="%s"}
WHERE AssocClass = Win32_LogicalDiskToPartition
''';
{ core code }
// the WMI Locator
WmiServices := CreateOleObject('WbemScripting.SWbemLocator');
// the connected services object
var WmiServicesConnect := WmiServices.ConnectServer('localhost', 'root\CIMV2');
Drives := WmiServicesConnect.ExecQuery('SELECT * FROM Win32_DiskDrive');
DrivesEnum := IUnknown(Drives._NewEnum) as IEnumVariant;
while DrivesEnum.Next(1, Drive, DriveValue) = 0 do
begin
DeviceId := Format('%s', [Drive.DeviceId]).Replace('\', '\\');
PartitionQuery := Format(CPartitionQuery, [DeviceId]);
Partitions := WmiServicesConnect.ExecQuery(PartitionQuery);
PartitionsEnum := IUnknown(Partitions._NewEnum) as IEnumVariant;
while PartitionsEnum.Next(1, Partition, PartitionValue) = 0 do
begin
DiskQuery := Format(CDiskQuery, [Partition.DeviceID]);
Disks := WmiServicesConnect.ExecQuery(DiskQuery);
DisksEnum := IUnknown(Disks._NewEnum) as IEnumVariant;
while DisksEnum.Next(1, Disk, DiskValue) = 0 do
begin
var info := TDriveInfo.Create(
disk.DeviceId,
drive.Caption,
drive.DeviceId,
partition.DeviceId,
drive.SerialNumber);
Result.Add(info);
Disk := Unassigned;
end;
Partition := Unassigned;
end;
Drive := Unassigned;
end;
The first query associates each physical drive with its partitions, while the second associates those partitions with their logical drives.