How do I find out how much disk space each user is currently using on a computer?
If you are using disk quotas, then use the Win32_DiskQuota class and retrieve the values of the User and DiskSpaceUsed properties.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_DiskQuota','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Disk Space Used %d',[Integer(FWbemObject.DiskSpaceUsed)]));
Writeln(Format('Quota Volume %s',[String(FWbemObject.QuotaVolume)]));
Writeln(Format('User %s',[String(FWbemObject.User)]));
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I determine when a removable drive has been added to or removed from a computer?
Use a monitoring code that queries the Win32_VolumeChangeEvent class.
function EventTypeStr(EventType:Integer):string;
begin
case EventType of
1 : Result:='Configuration Changed';
2 : Result:='Device Arrival';
3 : Result:='Device Removal';
4 : Result:='Docking';
end;
end;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
begin;
Writeln('Press Ctrl-C to terminate');
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecNotificationQuery('SELECT * FROM Win32_VolumeChangeEvent');
while true do
begin
FWbemObject := FWbemObjectSet.NextEvent;
if not VarIsClear(FWbemObject) then
begin
Writeln(Format('Drive Name %s',[String(FWbemObject.DriveName)]));
Writeln(Format('Event Type %s',[EventTypeStr(FWbemObject.EventType)]));
end;
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I determine if a CD is in a CD-ROM drive?
Use the Win32_CDROMDrive class and the MediaLoaded property.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_CDROMDrive','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Device ID %s',[String(FWbemObject.DeviceID)]));
Writeln(Format('Media Loaded %s',[String(FWbemObject.MediaLoaded)]));
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I distinguish between a fixed hard disk and a removable hard disk?
Use the Win32_LogicalDisk class and check the value of the DriveType property.
| Value | Meaning |
|---|---|
|
Unknown |
|
No Root Directory |
|
Removable Disk |
|
Local Disk |
|
Network Drive |
|
Compact Disc |
|
RAM Disk |
function DriveTypeStr(DriveType:integer): string;
begin
case DriveType of
0 : Result:='Unknown';
1 : Result:='No Root Directory';
2 : Result:='Removable Disk';
3 : Result:='Local Disk';
4 : Result:='Network Drive';
5 : Result:='CD/DVD Disc';
6 : Result:='RAM Disk';
end;
end;
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_LogicalDisk','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Device ID %s',[String(FWbemObject.DeviceID)]));
Writeln(Format('DriveType %s',[DriveTypeStr(FWbemObject.DriveType)]));
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I determine what file system is in use on a drive?
Use the Win32_LogicalDisk class and the FileSystem property.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_LogicalDisk','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Device ID %s',[String(FWbemObject.DeviceID)]));
if not VarIsNull(FWbemObject.FileSystem) then
Writeln(Format('File System %s',[String(FWbemObject.FileSystem)]));
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I determine how much free space is available on a drive?
Use the Win32_LogicalDisk class and the FreeSpace property.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_LogicalDisk','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Device ID %s',[String(FWbemObject.DeviceID)]));
if not VarIsNull(FWbemObject.FreeSpace) then
Writeln(Format('Free Space %d',[Int64(FWbemObject.FreeSpace)]));
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I determine the size of a drive?
Use the Win32_LogicalDisk class, and the Size property.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_LogicalDisk','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Device ID %s',[String(FWbemObject.DeviceID)]));
if not VarIsNull(FWbemObject.Size) then
Writeln(Format('Disk Size %d',[Int64(FWbemObject.Size)]));
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I find out what drives are mapped on a computer?
Use the Win32_MappedLogicalDisk class.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_MappedLogicalDisk','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Device ID %s',[String(FWbemObject.DeviceID)]));
Writeln(Format('Name %s',[String(FWbemObject.Name)]));
Writeln('');
FWbemObject:=Unassigned;
end;
end;
How do I defragment a hard disk?
Use the Win32_Volume class and the Defrag method.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_Volume Where Name = "F:\\" ','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
if oEnum.Next(1, FWbemObject, iValue) = 0 then
begin
FWbemObject.Defrag();
FWbemObject:=Unassigned;
end;
end;
How do I detect which drive letter is associated with a logical disk partition?
- Start with the Win32_DiskDrive class and query for instances of Win32_DiskPartition using the DeviceID property and the Win32_DiskDriveToDiskPartition association class. Now you have a collection of the partitions on the physical drive.
- Query for the Win32_LogicalDisk that represents the partition using the Win32_DiskPartition.DeviceID property and Win32_LogicalDiskToPartition association class.
- Get the drive letter from the Win32_LogicalDisk.DeviceID.
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
wmiDiskDrives : OLEVariant;
wmiDiskPartitions : OLEVariant;
wmiLogicalDisks : OLEVariant;
wmiDiskDrive : OLEVariant;
wmiDiskPartition : OLEVariant;
wmiLogicalDisk : OLEVariant;
oEnum : IEnumvariant;
oEnum2 : IEnumvariant;
oEnum3 : IEnumvariant;
iValue : LongWord;
DeviceID : string;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
//Get the physical disk drive
wmiDiskDrives := FWMIService.ExecQuery('SELECT Caption, DeviceID FROM Win32_DiskDrive','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(wmiDiskDrives._NewEnum) as IEnumVariant;
while oEnum.Next(1, wmiDiskDrive, iValue) = 0 do
begin
//Use the disk drive device id to find associated partition
DeviceID:=StringReplace(String(wmiDiskDrive.DeviceID),'\','\\',[rfReplaceAll]);
wmiDiskPartitions := FWMIService.ExecQuery('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="'+DeviceID+'"} WHERE AssocClass = Win32_DiskDriveToDiskPartition','WQL',wbemFlagForwardOnly);
oEnum2 := IUnknown(wmiDiskPartitions._NewEnum) as IEnumVariant;
while oEnum2.Next(1, wmiDiskPartition, iValue) = 0 do
begin
wmiLogicalDisks := FWMIService.ExecQuery('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="'+String(wmiDiskPartition.DeviceID)+'"} WHERE AssocClass = Win32_LogicalDiskToPartition','WQL',wbemFlagForwardOnly);
oEnum3 := IUnknown(wmiLogicalDisks._NewEnum) as IEnumVariant;
while oEnum3.Next(1, wmiLogicalDisk, iValue) = 0 do
begin
Writeln(Format('Drive letter associated with disk drive %s %s Partition %s is %s',[String(wmiDiskDrive.Caption),String(wmiDiskDrive.DeviceID),String(wmiDiskPartition.DeviceID),String(wmiLogicalDisk.DeviceID)]));
wmiLogicalDisk:=Unassigned;
end;
wmiDiskPartition:=Unassigned;
end;
wmiDiskDrive:=Unassigned;
Writeln;
end;
end;
This post is based in the MSDN entry WMI Tasks: Disks and File Systems
October 25, 2011 at 4:34 pm
How do you specify a drive letter for a FWMIService.ExecQuery rather than selecting * all drives? For example:
function WMIGetFreeDiskSpace( aDrive: string ): string; { Return the free disk space of a drive } const wbemFlagForwardOnly = $00000020; var FSWbemLocator : OLEVariant; FWMIService : OLEVariant; FWbemObjectSet: OLEVariant; FWbemObject : OLEVariant; oEnum : IEnumvariant; iValue : LongWord; begin; FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', ''); // specify a drive letter? FWbemObjectSet:= FWMIService.ExecQuery('SELECT ' + aDrive + ' FROM Win32_LogicalDisk','WQL',wbemFlagForwardOnly); oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant; while oEnum.Next(1, FWbemObject, iValue) = 0 do begin //Result := Format('Device ID %s',[String(FWbemObject.DeviceID)]); if not VarIsNull(FWbemObject.FreeSpace) then Result := Format('%s',[string(FWbemObject.FreeSpace)]); FWbemObject:=Unassigned; end; end;October 25, 2011 at 4:46 pm
try this
function WMIGetFreeDiskSpace( const aDrive: string ): Int64; const wbemFlagForwardOnly = $00000020; var FSWbemLocator : OLEVariant; FWMIService : OLEVariant; FWbemObjectSet: OLEVariant; FWbemObject : OLEVariant; oEnum : IEnumvariant; iValue : LongWord; begin; FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', ''); FWbemObjectSet:= FWMIService.ExecQuery(Format('SELECT Size FROM Win32_LogicalDisk Where DeviceID="%s"',[aDrive]),'WQL',wbemFlagForwardOnly); oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant; if oEnum.Next(1, FWbemObject, iValue) = 0 then begin Result:=Int64(FWbemObject.Size); FWbemObject:=Unassigned; end; end;and use like this
WMIGetFreeDiskSpace('C:')October 25, 2011 at 4:51 pm
Thanks…
October 25, 2011 at 7:17 pm
This function fails because while oEnum.Next( 1, FWbemObject, iValue ) 0.
Why would it not be 0? WMIGetDriveTypei( aDrive ) = 5 returns true but oEnum.Next( 1, FWbemObject, iValue ) 0.
function WMICDInDrive( aDrive: string ): string; { determine if a CD is in a CD-ROM drive } const wbemFlagForwardOnly = $00000020; var FSWbemLocator: OleVariant; FWMIService: OleVariant; FWbemObjectSet: OleVariant; FWbemObject: OleVariant; oEnum: IEnumvariant; iValue: LongWord; ullBoolean: boolean; ullBooleanS: string; begin // is drive a CD/DVD Disc if WMIGetDriveTypei( aDrive ) = 5 then begin FSWbemLocator := CreateOleObject( 'WbemScripting.SWbemLocator' ); FWMIService := FSWbemLocator.ConnectServer( 'localhost', 'root\CIMV2', '', '' ); FWbemObjectSet := FWMIService.ExecQuery( Format( 'SELECT MediaLoaded FROM Win32_CDROMDrive Where DeviceID="%s"', [ aDrive ] ), 'WQL', wbemFlagForwardOnly ); oEnum := IUnknown( FWbemObjectSet._NewEnum ) as IEnumvariant; while oEnum.Next( 1, FWbemObject, iValue ) = 0 do begin ullBoolean := FWbemObject.MediaLoaded; ullBooleanS := BoolToYesNo( ullBoolean ); Result := Format( '%s', [ ullBooleanS ] ); FWbemObject := Unassigned; end; end else Result := 'Not CD/DVD Disc'; end;October 25, 2011 at 7:59 pm
In the query against the Win32_CDROMDrive class you must use to compare the Drive property not DeviceID.
So you must write a code like this
Another advice, it seems which you are writting a set of helper functions to retrieve hardware information. If you want improve the performance use a single WMI connection and share that connection between the ExecQuery calls.
October 25, 2011 at 9:48 pm
If i call WMI at system startup period and WMI service is not ready, what will happen? Getting information failed or wait for WMI sevice ready and return ok automaticly?
October 26, 2011 at 8:42 pm
If the WMI service is stopped, the WMI operation will fail.
October 26, 2011 at 12:36 pm
“If you want improve the performance use a single WMI connection and share that connection between the ExecQuery calls.” Is this what you mean:
unit uWMI; interface uses Windows, Classes, ComCtrls, SysUtils, Variants, FileCtrl, ShellAPI, ShLwApi, ActiveX, ComObj; var FSWbemLocator: OleVariant; FWMIService: OleVariant; implementation function ConnectWithWMIServer: OleVariant; { Return WMI Server - Called once at program startup } var FSWbemLocator: OleVariant; begin FSWbemLocator := CreateOleObject( 'WbemScripting.SWbemLocator' ); Result := FSWbemLocator.ConnectServer( 'localhost', 'root\CIMV2', '', '' ); end; function WMICDInDrive( aDrive: string ): string; { Determine if a CD is in a CD-ROM drive } const wbemFlagForwardOnly = $00000020; var FWbemObjectSet: OleVariant; FWbemObject: OleVariant; oEnum: IEnumvariant; iValue: LongWord; ullBoolean: boolean; ullBooleanS: string; begin if not VarIsNull( FWMIService ) then begin // is drive a CD/DVD Disc if WMIGetDriveTypei( aDrive ) = 5 then begin FWbemObjectSet := FWMIService.ExecQuery( Format( 'SELECT MediaLoaded FROM Win32_CDROMDrive Where Drive="%s"', [ aDrive ] ), 'WQL', wbemFlagForwardOnly ); oEnum := IUnknown( FWbemObjectSet._NewEnum ) as IEnumvariant; while oEnum.Next( 1, FWbemObject, iValue ) = 0 do begin ullBoolean := FWbemObject.MediaLoaded; ullBooleanS := BoolToYesNo( ullBoolean ); Result := Format( '%s', [ ullBooleanS ] ); FWbemObject := Unassigned; end; end else Result := 'Not CD/DVD Disc'; end; end; // Usage: // procedure TFormMain.FormCreate( Sender: TObject ); begin ... FWMIService := ConnectWithWMIServer; end; procedure TFormMain.PageControl1Change( Sender: TObject ); begin case PageControl1.ActivePageIndex of ... 10: // Disk begin CDInDrive1.Caption := 'CD in Drive E: ' + WMICDInDrive('E:'); end; end; //case end;I have all of your snippets in this unit as functions and procedures. At the moment everything works except two functions… When I finish would you like the demo and unit?
October 26, 2011 at 8:30 pm
Yes something like that, but I prefear use a class with all the logic encapsulated instead of global variables.
October 27, 2011 at 7:35 am
good and nice code!