Title: WMI Methods and the Registry
Previous FAQ: FAQ102-7315: Get System information from WMI
As recalled in the previous FAQ, the discussion was on how to obtain system information from WMI. Several wrapper routines were provided in that FAQ and they will be used on these examples as well.
As one may notice in the MSDN WMI documentation, some of the WMI objects have methods attached to them. Here, how to call these methods will be described. Furthermore, since method calls are required to access the registry in WMI, an example of registry access will be provided as well.
Example #1: Starting a Service
This example presupposes that a combobox was filled prior to it with values that were obtained from the statement select caption from Win32_Service. This is not shown since it covers material involved in the first FAQ.
As well, the status of this service is not checked, though it can be done easily through using the OnSelect event of the ComboBox and the buttons enabled or disabled as dictated.
The method to start a service is simply Win32_Service.StartService. No parameters. This is because all methods, when dictated in directions, operate on the current selected record. This means we have to go out and get that record before we call the method. This is reasonably standard for most methods in WMI.
Example Code is below:
CODE
procedure TForm1.Button2Click(Sender: TObject);
// start service
var
WbemLocator: ISWbemLocator;
WbemServices: ISWbemServices;
ObjectSet: ISWbemObjectSet;
InParam: ISWBemObject;
tempobj: OleVariant;
InProcess: ISWBemObject;
RowENum: IENumVariant;
outstmt: string;
begin
WBemLocator := WMIStart;
WBemServices := WMIConnect(WBemLocator, '', '', '');
outstmt := 'Select caption from Win32_Service where caption = ''' +
ComboBox1.Items[ComboBox1.Itemindex] + '''';
ObjectSet := WMIExecQuery(WbemServices, outstmt);
WMIRowFindFirst(ObjectSet, RowENum, tempobj);
InProcess := IUnknown(tempobj) as ISWbemobject;
InParam := InProcess.ExecMethod_('StartService', nil, 0, nil);
end;
Example #2: Obtaining a key from the registry.
Those of you who are familiar with TRegistry will know there are a great many methods there to access and use the registry. The registry object in WMI is no different. This example will focus on obtaining a string from a specific path.
The first thing to note from this example is that the connection process to WMI is a bit different. The registry object, StdRegProv, is located in the namespace "default", which involves a slightly different connection process.
This method call is a lot more complex, showing the process of providing parms and retrieving them from the method when done.
CODE
unit regunit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
activex, wmiserv, WbemScripting_TLBa, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
WBEMLocator: SWBEMLocator;
WBEMServices: ISWBEMServices;
regobject: ISWBemObject;
InParam, OutParam: ISWBemObject;
InProp: ISWBemProperty;
outv: Olevariant;
begin
WBEMLocator := WMIStart;
WBemServices := WMIRegConnect(WBEMLocator, '', '', '');
WMIGetMethodInfo(WBEMServices, regobjstring, 'GetExpandedStringValue',
regobject, InParam);
WMISetValue(InParam, 'hDefKey', HKEY_CURRENT_USER);
WMISetValue(InParam, 'sSubKeyName', 'Control Panel\Desktop');
WMISetValue(InParam, 'sValueName', 'Wallpaper');
OutParam := regobject.ExecMethod_('GetExpandedStringValue', InParam, 0, nil);
// output value is SValue
InProp := OutParam.Properties_.Item('sValue', 0);
outv := InProp.Get_Value;
ShowMessage(outv); // the value of the registry key
end;
end.
Additional code below, which can be inserted into WMISERV.PAS in the last FAQ in the appropriate spots
CODE
const
regobjstring = 'StdRegProv';
function WMIRegConnect(WBemLocator: ISWBemLocator; Server, account, password: string): ISWBemServices;
// connects to the default area
begin
Result := nil;
try
Result := WBEMLocator.ConnectServer(Server, 'root\default', '', Account,
Password, '', 0, nil);
except
on EOleException do
raise EOleException.Create('incorrect credentials. WMI connection failed.', 1, '', '', 0);
end;
CoSetProxyBlanket(Result, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
nil,
wbemAuthenticationLevelCall, wbemImpersonationLevelImpersonate,
nil, EOAC_NONE);
end;
procedure WMIGetMethodInfo(srv: ISWbemServices; objname, method: string; var regobject, inparms: ISWBemObject);
// gets method info and parms, this is useful if an object method is *NOT* tied to a specific record.
begin
regobject := srv.Get(objname, 0, nil);
InParms := regobject.Methods_.Item(method, 0).InParameters;
end;
procedure WMISetValue(InParam: ISWBemObject; keyvalue: string; invalue: OleVariant);
// sets a parm value. Calls my modified set_value.
// remove the @ if you wish to make the default call.
begin
InParam.Properties_.Item(keyvalue, 0).Set_Value(@InValue);
end;