Due to many developers don’t know how access the WMI from Pascal code, I decided to write this entry to show a simple set of samples using Delphi Win32, Delphi.Net, Oxygene and Free-pascal.
Delphi .Net
Delphi Prism
Delphi win32 importing the Microsoft WMIScripting Library.
Delphi win32 Late-binding.
Lazarus Late-binding
UPDATE
To access the WMI using COM you must check this article
Accesing the WMI from Delphi and FPC via COM (without late binding or WbemScripting_TLB)
All the code samples uses the Win32_BaseBoard wmi class and are console applications just for simplicity.
The code showed in this entry can be optimized a lot for experienced developers, these simple piece of code only pretend give a basic idea which how connect to the WMi service and retieve data using a WQL query.
This is the Managed Object Format (MOF) representation of this class.
class Win32_BaseBoard : CIM_Card
{
string Caption;
string ConfigOptions[];
string CreationClassName;
real32 Depth;
string Description;
real32 Height;
boolean HostingBoard;
boolean HotSwappable;
datetime InstallDate;
string Manufacturer;
string Model;
string Name;
string OtherIdentifyingInfo;
string PartNumber;
boolean PoweredOn;
string Product;
boolean Removable;
boolean Replaceable;
string RequirementsDescription;
boolean RequiresDaughterBoard;
string SerialNumber;
string SKU;
string SlotLayout;
boolean SpecialRequirements;
string Status;
string Tag;
string Version;
real32 Weight;
real32 Width;
};
Using Delphi Win32 and importing the Microsoft WMIScripting Library
This must be the most used method for accessing the WMI from Delphi Win32, basically consist in import the Microsoft WMIScripting Library and then delphi will create a wrapper containing all the types, const and enumerations to access the WMI, the main objects(interfaces) are ISWbemServices (which create a connection with WMI Windows Service) , ISWbemObjectSet (Execute a WQL Query) and ISWbemPropertySet
Check the picture to see the Microsoft Wmi Scripting library organization.

The basics steps are
1) import the Microsoft WMIScripting Library

2) Establish a connection with the WMI service in a local o remote computer. using the TSWbemLocator.ConnectServer function.
function ConnectServer(const strServer: WideString; const strNamespace: WideString;
const strUser: WideString; const strPassword: WideString;
const strLocale: WideString; const strAuthority: WideString;
iSecurityFlags: Integer; const objWbemNamedValueSet: IDispatch): ISWbemServices;
SWbemServices := CoSWbemLocator.Create.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);
3) Execute your WQL Query using the ISWbemServices.ExecQuery function which returns a instance to the ISWbemObjectSet object.
this is the declaration of the ISWbemServices.ExecQuery
function ExecQuery(const strQuery: WideString; const strQueryLanguage: WideString;
iFlags: Integer; const objWbemNamedValueSet: IDispatch): ISWbemObjectSet; safecall;
and this is a sample of calling this function
SWbemObjectSet := SWbemServices.ExecQuery('SELECT * FROM Win32_BaseBoard','WQL', 0, nil);
4) the next step is iterate over the returned data, to do this we can use the ISWbemObjectSet._NewEnum property wich return an enumerator to the collection returned by the SWbemObjectSet
so using a IEnumVariant (which is part of the ActiveX unit) variable we can obtain the enumerator to the collection in this way.
Enum := (SWbemObjectSet._NewEnum) as IEnumVariant;
5) finally we need access the properties of the current collection, using the SWbemObject.Properties_.Item function
while (Enum.Next(1, TempObj, Value) = S_OK) do
begin
SWbemObject := IUnknown(tempObj) as ISWBemObject;
SWbemPropertySet:= SWbemObject.Properties_;
SWbemPropertySet.Item('SerialNumber', 0).Get_Value;//Get the value of the SerialNumber property
end;
Advantages of importing the Microsoft WMIScripting Library
1) Full access through the IDE (code-completion) to the types, enumerations and constants of the WMIScripting Library.
2) easy to debug syntax errors which would have been missed had you used late binding.
Drawbacks
1) Depending of the Windows version which you uses, you can get different results when you import the WMIScripting Library, check this link.
2) The final exe size is incremented when you import this library.
Check the full sample source code to get a idea how use this method.
program WmiDelphiWin32_Tlb;
{$APPTYPE CONSOLE}
uses
ActiveX,
Variants,
SysUtils,
WbemScripting_TLB in '..\..\..\Documents\RAD Studio\5.0\Imports\WbemScripting_TLB.pas';//
function VarArrayToStr(const vArray: variant): string;
function _VarToStr(const V: variant): string;
var
Vt: integer;
begin
Vt := VarType(V);
case Vt of
varSmallint,
varInteger : Result := IntToStr(integer(V));
varSingle,
varDouble,
varCurrency : Result := FloatToStr(Double(V));
varDate : Result := VarToStr(V);
varOleStr : Result := WideString(V);
varBoolean : Result := VarToStr(V);
varVariant : Result := VarToStr(Variant(V));
varByte : Result := char(byte(V));
varString : Result := String(V);
varArray : Result := VarArrayToStr(Variant(V));
end;
end;
var
i : integer;
begin
Result := '[';
if (VarType(vArray) and VarArray)=0 then
Result := _VarToStr(vArray)
else
for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do
if i=VarArrayLowBound(vArray, 1) then
Result := Result+_VarToStr(vArray[i])
else
Result := Result+'|'+_VarToStr(vArray[i]);
Result:=Result+']';
end;
function VarStrNull(const V:OleVariant):string; //avoid problems with null strings
begin
Result:='';
if not VarIsNull(V) then
begin
if VarIsArray(V) then
Result:=VarArrayToStr(V)
else
Result:=VarToStr(V);
end;
end;
Procedure GetWin32_BaseBoardInfo;
var
SWbemServices : ISWbemServices;
SWbemObjectSet : ISWbemObjectSet;
Item : Variant;
Enum : IEnumVariant;
TempObj : OleVariant;
Value : Cardinal;
SWbemObject : ISWbemObject;
SWbemPropertySet: ISWbemPropertySet;
begin
SWbemServices := CoSWbemLocator.Create.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);
SWbemObjectSet := SWbemServices.ExecQuery('SELECT * FROM Win32_BaseBoard','WQL', 0, nil);
Enum := (SWbemObjectSet._NewEnum) as IEnumVariant;
while (Enum.Next(1, TempObj, Value) = S_OK) do
begin
SWbemObject := IUnknown(tempObj) as ISWBemObject;
SWbemPropertySet:= SWbemObject.Properties_;
Writeln(Format('Caption %s',[VarStrNull(SWbemPropertySet.Item('Caption', 0).Get_Value)]));// String
Writeln(Format('ConfigOptions %s',[VarStrNull(SWbemPropertySet.Item('ConfigOptions', 0).Get_Value)]));// String
Writeln(Format('CreationClassName %s',[VarStrNull(SWbemPropertySet.Item('CreationClassName', 0).Get_Value)]));// String
Writeln(Format('Depth %s',[VarStrNull(SWbemPropertySet.Item('Depth', 0).Get_Value)]));// Real32
Writeln(Format('Description %s',[VarStrNull(SWbemPropertySet.Item('Description', 0).Get_Value)]));// String
Writeln(Format('Height %s',[VarStrNull(SWbemPropertySet.Item('Height', 0).Get_Value)]));// Real32
Writeln(Format('HostingBoard %s',[VarStrNull(SWbemPropertySet.Item('HostingBoard', 0).Get_Value)]));// Boolean
Writeln(Format('HotSwappable %s',[VarStrNull(SWbemPropertySet.Item('HotSwappable', 0).Get_Value)]));// Boolean
Writeln(Format('InstallDate %s',[VarStrNull(SWbemPropertySet.Item('InstallDate', 0).Get_Value)]));// Datetime
Writeln(Format('Manufacturer %s',[VarStrNull(SWbemPropertySet.Item('Manufacturer', 0).Get_Value)]));// String
Writeln(Format('Model %s',[VarStrNull(SWbemPropertySet.Item('Model', 0).Get_Value)]));// String
Writeln(Format('Name %s',[VarStrNull(SWbemPropertySet.Item('Name', 0).Get_Value)]));// String
Writeln(Format('OtherIdentifyingInfo %s',[VarStrNull(SWbemPropertySet.Item('OtherIdentifyingInfo', 0).Get_Value)]));// String
Writeln(Format('PartNumber %s',[VarStrNull(SWbemPropertySet.Item('PartNumber', 0).Get_Value)]));// String
Writeln(Format('PoweredOn %s',[VarStrNull(SWbemPropertySet.Item('PoweredOn', 0).Get_Value)]));// Boolean
Writeln(Format('Product %s',[VarStrNull(SWbemPropertySet.Item('Product', 0).Get_Value)]));// String
Writeln(Format('Removable %s',[VarStrNull(SWbemPropertySet.Item('Removable', 0).Get_Value)]));// Boolean
Writeln(Format('Replaceable %s',[VarStrNull(SWbemPropertySet.Item('Replaceable', 0).Get_Value)]));// Boolean
Writeln(Format('RequirementsDescription %s',[VarStrNull(SWbemPropertySet.Item('RequirementsDescription', 0).Get_Value)]));// String
Writeln(Format('RequiresDaughterBoard %s',[VarStrNull(SWbemPropertySet.Item('RequiresDaughterBoard', 0).Get_Value)]));// Boolean
Writeln(Format('SerialNumber %s',[VarStrNull(SWbemPropertySet.Item('SerialNumber', 0).Get_Value)]));// String
Writeln(Format('SKU %s',[VarStrNull(SWbemPropertySet.Item('SKU', 0).Get_Value)]));// String
Writeln(Format('SlotLayout %s',[VarStrNull(SWbemPropertySet.Item('SlotLayout', 0).Get_Value)]));// String
Writeln(Format('SpecialRequirements %s',[VarStrNull(SWbemPropertySet.Item('SpecialRequirements', 0).Get_Value)]));// Boolean
Writeln(Format('Status %s',[VarStrNull(SWbemPropertySet.Item('Status', 0).Get_Value)]));// String
Writeln(Format('Tag %s',[VarStrNull(SWbemPropertySet.Item('Tag', 0).Get_Value)]));// String
Writeln(Format('Version %s',[VarStrNull(SWbemPropertySet.Item('Version', 0).Get_Value)]));// String
Writeln(Format('Weight %s',[VarStrNull(SWbemPropertySet.Item('Weight', 0).Get_Value)]));// Real32
Writeln(Format('Width %s',[VarStrNull(SWbemPropertySet.Item('Width', 0).Get_Value)]));// Real32
Writeln('');
TempObj:=Unassigned;
end;
end;
begin
try
CoInitialize(nil);
try
GetWin32_BaseBoardInfo;
Readln;
finally
CoUninitialize;
end;
except
on E:Exception do
begin
Writeln(E.Classname, ':', E.Message);
Readln;
end;
end;
end.
Using Delphi and Late-Binding
Using the CreateOleObject function
You can access the WMI using the CreateOleObject function from delphi passing the WbemScripting.SWbemLocator class name
var
FSWbemLocator : OLEVariant;
begin
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
//
end;
And then to run a WQL sentence
const
WbemUser ='';
WbemPassword ='';
WbemComputer ='localhost';
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
//create an instance to the WMI Scripting SWbemLocator
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
//connect to the server
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
//execute the WQL sentence
FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_BaseBoard','WQL',wbemFlagForwardOnly);
//get the enumerator
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
//traverse the data
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('Caption %s',[FWbemObject.Caption]));// String
Writeln('');
FWbemObject:=Unassigned;
end;
end;
Using a Moniker
Another way to access the WMI is using a Moniker, to do this we need to use the IBindCtx and IMoniker interfaces.
Check this sample to create a wmi instance using these interfaces.
function GetWMIObject(const objectName: String): IDispatch;
var
chEaten: Integer;
BindCtx: IBindCtx;//for access to a bind context
Moniker: IMoniker;//Enables you to use a moniker object
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));//Converts a string into a moniker that identifies the object named by the string
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));//Binds to the specified object
end;
//and call in this way
GetWMIObject('winmgmts:\\localhost\root\CIMV2');
Now we can run the query an get the results
See the snippet, is very similar to the used when we import the WbemScripting_TLB unit. but the main difference is which all the variables are declarated as Variants (OLEVariant) because we don’t have available the types, enumeratios and constants of the WbemScripting_TLB unit.
var
objWMIService : OLEVariant;
colItems : OLEVariant;
colItem : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2');
colItems := objWMIService.ExecQuery('SELECT * FROM Win32_BaseBoard','WQL',0);
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
3) finally to access a particular property we can get the value directly using his name.
while oEnum.Next(1, colItem, iValue) = 0 do
begin
Writeln('Serial Number : '+colItem.SerialNumber);
colItem:=Unassigned; //avoid memory leaks caused by the oEnum.Next function
end;
Advantages of Late Binding
1. Is a very flexible solution to access the WMI, and the code to manage the wmi objects is very close to vbscript, which is good because there are thousands of examples of vbscript on the Internet to access the WMI Data.
2. Another very important advantage is that code which uses late binding is more certain to be version-independent, because when you create a WMIObject using winmgmts you are not referencing any particular version of the WMI.
3. The final exe executable is small because you don’t import any wrapper.
Drawbacks
1. You don’t have access to the wmi types, constants and enumerations from the ide, because the code is interpreted in run-time.
2. Hard to debug syntax errors,because the compiler don’t know about the WMI types
so you can write something like this (which is wrong) and the code will be compiled anyway.
colItems.Properties_('Prop').Qualifiers_;
the right version must be.
colItems.Properties_.Item('Prop').Qualifiers_;
Check the code using Late Binding to access the WMI from delphi (Valid for versions 5 to XE)
program WmiDelphiWin32_LateBinding;
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX,
ComObj,
Variants;//introduced in delphi 6, if you use a older version of delphi you just remove this
function VarArrayToStr(const vArray: variant): string;
function _VarToStr(const V: variant): string;
var
Vt: integer;
begin
Vt := VarType(V);
case Vt of
varSmallint,
varInteger : Result := IntToStr(integer(V));
varSingle,
varDouble,
varCurrency : Result := FloatToStr(Double(V));
varDate : Result := VarToStr(V);
varOleStr : Result := WideString(V);
varBoolean : Result := VarToStr(V);
varVariant : Result := VarToStr(Variant(V));
varByte : Result := char(byte(V));
varString : Result := String(V);
varArray : Result := VarArrayToStr(Variant(V));
end;
end;
var
i : integer;
begin
Result := '[';
if (VarType(vArray) and VarArray)=0 then
Result := _VarToStr(vArray)
else
for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do
if i=VarArrayLowBound(vArray, 1) then
Result := Result+_VarToStr(vArray[i])
else
Result := Result+'|'+_VarToStr(vArray[i]);
Result:=Result+']';
end;
function VarStrNull(const V:OleVariant):string; //avoid problems with null strings
begin
Result:='';
if not VarIsNull(V) then
begin
if VarIsArray(V) then
Result:=VarArrayToStr(V)
else
Result:=VarToStr(V);
end;
end;
function GetWMIObject(const objectName: String): IDispatch; //create the Wmi instance
var
chEaten: Integer;
BindCtx: IBindCtx;
Moniker: IMoniker;
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
end;
//The Win32_BaseBoard class represents a base board (also known as a motherboard
//or system board).
procedure GetWin32_BaseBoardInfo;
var
objWMIService : OLEVariant;
colItems : OLEVariant;
colItem : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2');
colItems := objWMIService.ExecQuery('SELECT * FROM Win32_BaseBoard','WQL',0);
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
while oEnum.Next(1, colItem, iValue) = 0 do
begin
Writeln(Format('Caption %s',[VarStrNull(colItem.Caption)]));// String
Writeln(Format('ConfigOptions %s',[VarStrNull(colItem.ConfigOptions)]));// String
Writeln(Format('CreationClassName %s',[VarStrNull(colItem.CreationClassName)]));// String
Writeln(Format('Depth %s',[VarStrNull(colItem.Depth)]));// Real32
Writeln(Format('Description %s',[VarStrNull(colItem.Description)]));// String
Writeln(Format('Height %s',[VarStrNull(colItem.Height)]));// Real32
Writeln(Format('HostingBoard %s',[VarStrNull(colItem.HostingBoard)]));// Boolean
Writeln(Format('HotSwappable %s',[VarStrNull(colItem.HotSwappable)]));// Boolean
Writeln(Format('InstallDate %s',[VarStrNull(colItem.InstallDate)]));// Datetime
Writeln(Format('Manufacturer %s',[VarStrNull(colItem.Manufacturer)]));// String
Writeln(Format('Model %s',[VarStrNull(colItem.Model)]));// String
Writeln(Format('Name %s',[VarStrNull(colItem.Name)]));// String
Writeln(Format('OtherIdentifyingInfo %s',[VarStrNull(colItem.OtherIdentifyingInfo)]));// String
Writeln(Format('PartNumber %s',[VarStrNull(colItem.PartNumber)]));// String
Writeln(Format('PoweredOn %s',[VarStrNull(colItem.PoweredOn)]));// Boolean
Writeln(Format('Product %s',[VarStrNull(colItem.Product)]));// String
Writeln(Format('Removable %s',[VarStrNull(colItem.Removable)]));// Boolean
Writeln(Format('Replaceable %s',[VarStrNull(colItem.Replaceable)]));// Boolean
Writeln(Format('RequirementsDescription %s',[VarStrNull(colItem.RequirementsDescription)]));// String
Writeln(Format('RequiresDaughterBoard %s',[VarStrNull(colItem.RequiresDaughterBoard)]));// Boolean
Writeln(Format('SerialNumber %s',[VarStrNull(colItem.SerialNumber)]));// String
Writeln(Format('SKU %s',[VarStrNull(colItem.SKU)]));// String
Writeln(Format('SlotLayout %s',[VarStrNull(colItem.SlotLayout)]));// String
Writeln(Format('SpecialRequirements %s',[VarStrNull(colItem.SpecialRequirements)]));// Boolean
Writeln(Format('Status %s',[VarStrNull(colItem.Status)]));// String
Writeln(Format('Tag %s',[VarStrNull(colItem.Tag)]));// String
Writeln(Format('Version %s',[VarStrNull(colItem.Version)]));// String
Writeln(Format('Weight %s',[VarStrNull(colItem.Weight)]));// Real32
Writeln(Format('Width %s',[VarStrNull(colItem.Width)]));// Real32
Writeln('');
colItem:=Unassigned;
end;
end;
begin
try
CoInitialize(nil);
try
GetWin32_BaseBoardInfo;
Readln;
finally
CoUninitialize;
end;
except
on E:Exception do
begin
Writeln(E.Classname, ':', E.Message);
Readln;
end;
end;
end.
Using Delphi .Net (Valid for versions 2005, 2006, 2007)
1) before to use the .net wmi objects you add the System.Management reference to your project.

2) Now we need make the connection to the WMi service, to do this you must use the System.Management namespace and the ManagementObjectSearcher class wich have several constructor to facilitate the connection with the wmi, this class is very versatile and let establish the connection and make a WQL query in a single step.
Check the constructors availables to this class
Public method ManagementObjectSearcher() //Initializes a new instance of the ManagementObjectSearcher class. After some properties on this object are set, the object can be used to invoke a query for management information. This is the default constructor.
Public method ManagementObjectSearcher(ObjectQuery) //Initializes a new instance of the ManagementObjectSearcher class used to invoke the specified query for management information.
Public method ManagementObjectSearcher(String) //Initializes a new instance of the ManagementObjectSearcher class used to invoke the specified query for management information.
Public method ManagementObjectSearcher(ManagementScope, ObjectQuery) //Initializes a new instance of the ManagementObjectSearcher class used to invoke the specified query in the specified scope.
Public method ManagementObjectSearcher(String, String) //Initializes a new instance of the ManagementObjectSearcher class used to invoke the specified query in the specified scope.
Public method ManagementObjectSearcher(ManagementScope, ObjectQuery, EnumerationOptions) //Initializes a new instance of the
Public method ManagementObjectSearcher class //to be used to invoke the specified query in the specified scope, with the specified options.
Public method ManagementObjectSearcher(String, String, EnumerationOptions) //Initializes a new instance of the ManagementObjectSearcher class used to invoke the specified query, in the specified scope, and with the specified options.
so to establishing the connection and make the query to the WMI you must write a code like this
Searcher :=ManagementObjectSearcher.Create('root\cimv2','SELECT * FROM Win32_BaseBoard');
3) retrieve the data using the ManagementObjectCollection object.
4) get a enumerator to iterate over the data returned using a ManagementObjectEnumerator
Collection:=Searcher.Get();//Get the data
iter:=Collection.GetEnumerator;//create a enumerator
while(iter.MoveNext()) do//iterate over the enumerator
5) and finally to access to the value of an particular property we must use a ManagementObject object in this way
WmiObject:=ManagementObject(iter.Current); //get the current element
SerialNumber:=WmiObject['SerialNumber'];
This is the full source code to access the wmi from Delphi .Net from a console application
program WmiDelphi.Net;
{$APPTYPE CONSOLE}
uses
System.Management,
SysUtils;
procedure GetWin32_BaseBoardInfo;
var
Searcher : ManagementObjectSearcher ;
Collection : ManagementObjectCollection;
iter : ManagementObjectCollection.ManagementObjectEnumerator;
WmiObject : ManagementObject;
begin
try
Searcher :=ManagementObjectSearcher.Create('SELECT * FROM Win32_BaseBoard'); //make the WMi query
Collection:=Searcher.Get();//Get the data
iter:=Collection.GetEnumerator;//create a enumerator
while(iter.MoveNext()) do//iterate over the enumerator
begin
WmiObject:=ManagementObject(iter.Current); //get the current element
Writeln(Format('Caption %s',[WmiObject['Caption']]));
Writeln(Format('ConfigOptions %s',[WmiObject['ConfigOptions']]));
Writeln(Format('CreationClassName %s',[WmiObject['CreationClassName']]));
Writeln(Format('Depth %s',[WmiObject['Depth']]));
Writeln(Format('Description %s',[WmiObject['Description']]));
Writeln(Format('Height %s',[WmiObject['Height']]));
Writeln(Format('HostingBoard %s',[WmiObject['HostingBoard']]));
Writeln(Format('HotSwappable %s',[WmiObject['HotSwappable']]));
Writeln(Format('InstallDate %s',[WmiObject['InstallDate']]));
Writeln(Format('Manufacturer %s',[WmiObject['Manufacturer']]));
Writeln(Format('Model %s',[WmiObject['Model']]));
Writeln(Format('Name %s',[WmiObject['Name']]));
Writeln(Format('OtherIdentifyingInfo %s',[WmiObject['OtherIdentifyingInfo']]));
Writeln(Format('PartNumber %s',[WmiObject['PartNumber']]));
Writeln(Format('PoweredOn %s',[WmiObject['PoweredOn']]));
Writeln(Format('Product %s',[WmiObject['Product']]));
Writeln(Format('Removable %s',[WmiObject['Removable']]));
Writeln(Format('Replaceable %s',[WmiObject['Replaceable']]));
Writeln(Format('RequirementsDescription %s',[WmiObject['RequirementsDescription']]));
Writeln(Format('RequiresDaughterBoard %s',[WmiObject['RequiresDaughterBoard']]));
Writeln(Format('SerialNumber %s',[WmiObject['SerialNumber']]));
Writeln(Format('SKU %s',[WmiObject['SKU']]));
Writeln(Format('SlotLayout %s',[WmiObject['SlotLayout']]));
Writeln(Format('SpecialRequirements %s',[WmiObject['SpecialRequirements']]));
Writeln(Format('Status %s',[WmiObject['Status']]));
Writeln(Format('Tag %s',[WmiObject['Tag']]));
Writeln(Format('Version %s',[WmiObject['Version']]));
Writeln(Format('Weight %s',[WmiObject['Weight']]));
Writeln(Format('Width %s',[WmiObject['Width']]));
end;
Readln;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end;
begin
try
GetWin32_BaseBoardInfo;
Readln;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
Using Delphi Prism
By far using .Net and delphi prism must be the easy way to access the WMI, because you don’t need to implement enumerators or helper functions to avoid nulls. therefore exists many resources of the WMI and .Net in the MSDN site.
1) to access the WMI from .Net you add the System.Management namespace which give you full access to the WMI.

2) Now using the ManagementObjectSearcher class in a single step you can establish a connection to the wmi service and make a WQL query.
Searcher := new ManagementObjectSearcher('root\cimv2','select * from Win32_BaseBoard');
3) for iterate over the WMI data you can use the great features of dephi-prism, how create a local variable in a for loop
for WmiObject : ManagementObject in searcher.Get() do //in this single line you are creating a WmiObject to get access to the properties,and searcher.Get() return a enumerator that iterates through the ManagementObjectCollection.
Finally the Source code of a Delphi Prism console application to access the WMI.
namespace WmiDelphiPrism;
interface
uses
System,
System.Management,
System.Text;
type
ConsoleApp = class
private
class method GetWin32_BaseBoardInfo;
public
class method Main;
end;
implementation
class method ConsoleApp.Main;
begin
try
GetWin32_BaseBoardInfo;
Console.Read();
except on E: Exception do
Console.WriteLine(E.ToString()+' Trace '+E.StackTrace );
end;
end;
class method ConsoleApp.GetWin32_BaseBoardInfo;
var
Searcher : ManagementObjectSearcher;
begin
Searcher := new ManagementObjectSearcher('root\cimv2','select * from Win32_BaseBoard');
for WmiObject : ManagementObject in searcher.Get() do
begin
Console.WriteLine('{0,-35} {1,-40}','Caption',WmiObject['Caption']);
Console.WriteLine('{0,-35} {1,-40}','ConfigOptions',WmiObject['ConfigOptions']);
Console.WriteLine('{0,-35} {1,-40}','CreationClassName',WmiObject['CreationClassName']);
Console.WriteLine('{0,-35} {1,-40}','Depth',WmiObject['Depth']);
Console.WriteLine('{0,-35} {1,-40}','Description',WmiObject['Description']);
Console.WriteLine('{0,-35} {1,-40}','Height',WmiObject['Height']);
Console.WriteLine('{0,-35} {1,-40}','HostingBoard',WmiObject['HostingBoard']);
Console.WriteLine('{0,-35} {1,-40}','HotSwappable',WmiObject['HotSwappable']);
Console.WriteLine('{0,-35} {1,-40}','InstallDate',WmiObject['InstallDate']);
Console.WriteLine('{0,-35} {1,-40}','Manufacturer',WmiObject['Manufacturer']);
Console.WriteLine('{0,-35} {1,-40}','Model',WmiObject['Model']);
Console.WriteLine('{0,-35} {1,-40}','Name',WmiObject['Name']);
Console.WriteLine('{0,-35} {1,-40}','OtherIdentifyingInfo',WmiObject['OtherIdentifyingInfo']);
Console.WriteLine('{0,-35} {1,-40}','PartNumber',WmiObject['PartNumber']);
Console.WriteLine('{0,-35} {1,-40}','PoweredOn',WmiObject['PoweredOn']);
Console.WriteLine('{0,-35} {1,-40}','Product',WmiObject['Product']);
Console.WriteLine('{0,-35} {1,-40}','Removable',WmiObject['Removable']);
Console.WriteLine('{0,-35} {1,-40}','Replaceable',WmiObject['Replaceable']);
Console.WriteLine('{0,-35} {1,-40}','RequirementsDescription',WmiObject['RequirementsDescription']);
Console.WriteLine('{0,-35} {1,-40}','RequiresDaughterBoard',WmiObject['RequiresDaughterBoard']);
Console.WriteLine('{0,-35} {1,-40}','SerialNumber',WmiObject['SerialNumber']);
Console.WriteLine('{0,-35} {1,-40}','SKU',WmiObject['SKU']);
Console.WriteLine('{0,-35} {1,-40}','SlotLayout',WmiObject['SlotLayout']);
Console.WriteLine('{0,-35} {1,-40}','SpecialRequirements',WmiObject['SpecialRequirements']);
Console.WriteLine('{0,-35} {1,-40}','Status',WmiObject['Status']);
Console.WriteLine('{0,-35} {1,-40}','Tag',WmiObject['Tag']);
Console.WriteLine('{0,-35} {1,-40}','Version',WmiObject['Version']);
Console.WriteLine('{0,-35} {1,-40}','Weight',WmiObject['Weight']);
Console.WriteLine('{0,-35} {1,-40}','Width',WmiObject['Width']);
end;
end;
end.
Using Lazarus
The code necessary to access the WMI from Free-pascal using lazarus is very similar to the used in the Delphi win32 Late-binding., so i will show the differences only because the general idea is the same.
1) you must add the Windows unit to the uses clause because this unit contan the PULONG type which is required in some functions.
2) you don’t need call CoInitialize and CoUninitialize functions because both are initializated by the comobj unit
3) the helper function GetWMIObject must be modified to fit with the new types of parameteres required by the MkParseDisplayName function.
which is declarated like this (see the _para3 param which is of PULONG (^cardinal) type)
function MkParseDisplayName(_para1:IBindCtx; _para2:POLESTR; out _para3:PULONG; out _para4:IMoniker):HRESULT;stdcall; external 'ole32.dll' name 'MkParseDisplayName';
and the modified helper function now look like this.
function GetWMIObject(const objectName: String): IDispatch; //create the Wmi instance
var
chEaten: PULONG;
BindCtx: IBindCtx;
Moniker: IMoniker;
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
end;
4) the function IEnumVARIANT.Next requires a Variant param
Function Next(celt: ULONG; OUT rgVar: VARIANT; pCeltFetched: pULONG=nil):HResult;StdCall;
so you must use it in this way
var
colItem : Variant;
//
//
//
while oEnum.Next(1, colItem, nil) = 0 do
5) finally if you wanna use the format function, you must aware which has some problems with variant values. so you must rewrite the code to show the info in this way.
SDummy:=VarStrNull(colItem.Caption); //SDummy is a string
Writeln(Format('Caption %s',[SDummy]));
Lazarus source code of console aplication to access the WMI
program WmiLazarus_LateBinding;
{$mode objfpc}
uses
SysUtils,
Variants,
comobj,//required for the OleCheck and CoInitialize functions
ActiveX,
Windows;//required for the PULONG type
function VarArrayToStr(const vArray: variant): string;
function _VarToStr(const V: variant): string;
var
Vt: integer;
begin
Vt := VarType(V);
case Vt of
varSmallint,
varInteger : Result := IntToStr(integer(V));
varSingle,
varDouble,
varCurrency : Result := FloatToStr(Double(V));
varDate : Result := VarToStr(V);
varOleStr : Result := WideString(V);
varBoolean : Result := VarToStr(V);
varVariant : Result := VarToStr(Variant(V));
varByte : Result := char(byte(V));
varString : Result := String(V);
varArray : Result := VarArrayToStr(Variant(V));
end;
end;
var
i : integer;
begin
Result := '[';
if (VarType(vArray) and VarArray)=0 then
Result := _VarToStr(vArray)
else
for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do
if i=VarArrayLowBound(vArray, 1) then
Result := Result+_VarToStr(vArray[i])
else
Result := Result+'|'+_VarToStr(vArray[i]);
Result:=Result+']';
end;
function VarStrNull(const V:OleVariant):string; //avoid problems with null strings
begin
Result:='';
if not VarIsNull(V) then
begin
if VarIsArray(V) then
Result:=VarArrayToStr(V)
else
Result:=VarToStr(V);
end;
end;
function GetWMIObject(const objectName: String): IDispatch; //create the Wmi instance
var
chEaten: PULONG;
BindCtx: IBindCtx;
Moniker: IMoniker;
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
end;
//The Win32_BaseBoard class represents a base board (also known as a motherboard
//or system board).
procedure GetWin32_BaseBoardInfo;
var
objWMIService : OleVariant;
colItems : OleVariant;
colItem : Variant;
oEnum : IEnumvariant;
SDummy : string;
begin;
objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2');
colItems := objWMIService.ExecQuery('SELECT * FROM Win32_BaseBoard','WQL',0);
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
while oEnum.Next(1, colItem, nil) = 0 do
begin
SDummy:=VarStrNull(colItem.Caption);
Writeln(Format('Caption %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.ConfigOptions);
Writeln(Format('ConfigOptions %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.CreationClassName);
Writeln(Format('CreationClassName %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Depth);
Writeln(Format('Depth %s',[SDummy]));// Real32
SDummy:=VarStrNull(colItem.Description);
Writeln(Format('Description %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Height);
Writeln(Format('Height %s',[SDummy]));// Real32
SDummy:=VarStrNull(colItem.HostingBoard);
Writeln(Format('HostingBoard %s',[SDummy]));// Boolean
SDummy:=VarStrNull(colItem.HotSwappable);
Writeln(Format('HotSwappable %s',[SDummy]));// Boolean
SDummy:=VarStrNull(colItem.InstallDate);
Writeln(Format('InstallDate %s',[SDummy]));// Datetime
SDummy:=VarStrNull(colItem.Manufacturer);
Writeln(Format('Manufacturer %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Model);
Writeln(Format('Model %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Name);
Writeln(Format('Name %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.OtherIdentifyingInfo);
Writeln(Format('OtherIdentifyingInfo %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.PartNumber);
Writeln(Format('PartNumber %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.PoweredOn);
Writeln(Format('PoweredOn %s',[SDummy]));// Boolean
SDummy:=VarStrNull(colItem.Product);
Writeln(Format('Product %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Removable);
Writeln(Format('Removable %s',[SDummy]));// Boolean
SDummy:=VarStrNull(colItem.Replaceable);
Writeln(Format('Replaceable %s',[SDummy]));// Boolean
SDummy:=VarStrNull(colItem.RequirementsDescription);
Writeln(Format('RequirementsDescription %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.RequiresDaughterBoard);
Writeln(Format('RequiresDaughterBoard %s',[SDummy]));// Boolean
SDummy:=VarStrNull(colItem.SerialNumber);
Writeln(Format('SerialNumber %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.SKU);
Writeln(Format('SKU %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.SlotLayout);
Writeln(Format('SlotLayout %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.SpecialRequirements);
Writeln(Format('SpecialRequirements %s',[SDummy]));// Boolean
SDummy:=VarStrNull(colItem.Status);
Writeln(Format('Status %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Tag);
Writeln(Format('Tag %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Version);
Writeln(Format('Version %s',[SDummy]));// String
SDummy:=VarStrNull(colItem.Weight);
Writeln(Format('Weight %s',[SDummy]));// Real32
SDummy:=VarStrNull(colItem.Width);
Writeln(Format('Width %s',[SDummy]));// Real32
end;
end;
begin
try
//CoInitialize(nil); you don't need call this because is initializated by the comobj unit
try
GetWin32_BaseBoardInfo;
Readln;
finally
//CoUninitialize;
end;
except
on E:Exception do
begin
Writeln(E.Classname, ':', E.Message);
Readln;
end;
end;
end.
So now you don’t have excuses to don’t use the WMI for pascal code. And remember which you have the WMI Delphi Code creator to help you.;)
-33.636934
-70.679350