Skip to content

Commit 6cd3daf

Browse files
committed
[wmi] recfactorized and improved classes
1 parent 4601c4c commit 6cd3daf

File tree

1 file changed

+212
-53
lines changed

1 file changed

+212
-53
lines changed

Quick.WMI.pas

+212-53
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{ ***************************************************************************
22
3-
Copyright (c) 2016-2019 Kike Pérez
3+
Copyright (c) 2016-2020 Kike Pérez
44
55
Unit : Quick.WMI
66
Description : Common functions
77
Author : Kike Pérez
8-
Version : 1.0
8+
Version : 1.1
99
Created : 04/04/2019
10-
Modified : 08/04/2019
10+
Modified : 22/04/2020
1111
1212
This file is part of QuickLib: https://github.com/exilon/QuickLib
1313
@@ -40,47 +40,99 @@ interface
4040

4141
uses
4242
SysUtils,
43-
WbemScripting_TLB,
4443
ActiveX,
4544
ComObj,
45+
Quick.Commons,
46+
Quick.Collections,
4647
Quick.Arrays,
4748
Quick.Value,
4849
Variants;
4950

5051
type
5152

52-
TFlexArray = TArray<TFlexValue>;
53+
IWMIInstance = interface
54+
['{4C81A6A6-4A65-46FB-B05B-5898DF51F9B7}']
55+
function GetProperty(const aPropertyName : string) : TFlexValue;
56+
function GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
57+
function GetName : string;
58+
end;
5359

54-
TWMIObject = record
60+
TWMIInstance = class(TInterfacedObject,IWMIInstance)
5561
private
5662
fInstance : string;
57-
fProperty : string;
63+
fWMIItem : OleVariant;
64+
public
65+
constructor Create(const aInstanceName : string; aWMIItem: OleVariant);
66+
destructor Destroy; override;
67+
function GetProperty(const aPropertyName : string) : TFlexValue;
68+
function GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
69+
function GetName : string;
5870
end;
5971

60-
TWMICollector = class
61-
private
62-
class function GetObject(const aObjectName: string) : IDispatch;
63-
public
64-
class function GetProperty(const aWMIHost, aRoot, aWMIClass, aWMIProperty : string) : TFlexValue;
65-
class function GetPropertyInstances(const aWMIHost, aRoot, aWMIClass,aWMIProperty : string; const aInstances : string = '*') : TFlexPairArray;
72+
TWMIInstances = TArray<IWMIInstance>;
73+
74+
IWMIClass = interface
75+
['{FAFE26ED-28BC-4591-AE5A-9E4543074B5C}']
76+
function GetInstance(const aInstance : string) : IWMIInstance;
77+
function GetInstances(const aInstances : TArray<string>) : TWMIInstances;
6678
end;
6779

68-
TWMIInstance = class
80+
TWMIClass = class(TInterfacedObject,IWMIClass)
6981
private
70-
fInstance : string;
82+
fClassName : string;
83+
fWMIService : OleVariant;
84+
fWMIClassItems : IEnumvariant;
85+
function GetInstanceName(aWMIClass : OleVariant) : string;
7186
public
72-
property Instance :
87+
constructor Create(aWMIService : OleVariant; const aClassName : string; aWMIClassItems : IEnumvariant);
88+
destructor Destroy; override;
89+
function GetInstance(const aInstance : string) : IWMIInstance;
90+
function GetInstances(const aInstances : TArray<string>) : TWMIInstances;
7391
end;
7492

75-
TWMIObject2 = class
93+
IWMICollector = interface
94+
['{3FFFF0DC-F533-4FE1-A511-73E76EC6BCC8}']
95+
function From(const aRoot, aWMIClass : string) : IWMIClass; overload;
96+
function From(const aHost, aRoot, aWMIClass : string) : IWMIClass; overload;
97+
end;
98+
99+
TWMICollector = class(TInterfacedObject,IWMICollector)
100+
private
101+
fNamespace : string;
102+
fWMIService : OleVariant;
76103
public
77-
function FromInstance(const aInstanceName : string) : TWMIInstance;
104+
constructor Create;
105+
destructor Destroy; override;
106+
class function GetObject(const aObjectName: string) : IDispatch;
107+
function From(const aRoot, aWMIClass : string) : IWMIClass; overload;
108+
function From(const aHost, aRoot, aWMIClass : string) : IWMIClass; overload;
78109
end;
79110

80111
EWMICollector = class(Exception);
81112

82113
implementation
83114

115+
const
116+
wbemFlagUseAmendedQualifiers = $00020000;
117+
wbemFlagReturnImmediately = $00000010;
118+
wbemFlagReturnWhenComplete = $00000000;
119+
wbemFlagForwardOnly = $00000020;
120+
121+
{ TWMICollector }
122+
123+
constructor TWMICollector.Create;
124+
begin
125+
fNamespace := '';
126+
CoInitialize(nil);
127+
end;
128+
129+
destructor TWMICollector.Destroy;
130+
begin
131+
fWMIService := Unassigned;
132+
CoUninitialize;
133+
inherited;
134+
end;
135+
84136
class function TWMICollector.GetObject(const aObjectName: string) : IDispatch;
85137
var
86138
chEaten : Integer;
@@ -92,59 +144,166 @@ class function TWMICollector.GetObject(const aObjectName: string) : IDispatch;
92144
OleCheck(Moniker.BindToObject(bindCtx, nil, IDispatch, Result));
93145
end;
94146

95-
class function TWMICollector.GetProperty(const aWMIHost, aRoot, aWMIClass, aWMIProperty: string) : TFlexValue;
147+
function TWMICollector.From(const aRoot, aWMIClass : string) : IWMIClass;
148+
begin
149+
Result := From('.',aRoot,aWMIClass);
150+
end;
151+
152+
function TWMICollector.From(const aHost, aRoot, aWMIClass : string) : IWMIClass;
96153
var
97-
objWMIService : OLEVariant;
98154
colItems : OLEVariant;
99-
colItem : OLEVariant;
100155
oEnum : IEnumvariant;
101-
iValue : LongWord;
102156
begin
103-
CoInitialize(nil);
104157
try
158+
//only connect if namespace is different from previous connection
159+
if fNamespace <> aHost + '\' + aRoot then
160+
begin
161+
fWMIService := GetObject(Format('winmgmts:\\%s\%s',[aHost,aRoot]));
162+
fNamespace := aHost + '\' + aRoot;
163+
end;
164+
colItems := fWMIService.ExecQuery(Format('SELECT * FROM %s',[aWMIClass]),'WQL',wbemFlagForwardOnly and wbemFlagReturnImmediately);
165+
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
166+
Result := TWMIClass.Create(fWMIService,aWMIClass,oEnum);
167+
except
168+
on E : Exception do raise EWMICollector.CreateFmt('Error getting WMI Class "\\%s\%s\%s": %s',[aHost,aRoot,aWMIClass,e.Message]);
169+
end;
170+
end;
171+
172+
{ TWMIInstance }
173+
174+
constructor TWMIInstance.Create(const aInstanceName : string; aWMIItem: OleVariant);
175+
begin
176+
fInstance := aInstanceName;
177+
fWMIItem := aWMIItem;
178+
end;
179+
180+
destructor TWMIInstance.Destroy;
181+
begin
182+
fWMIItem := Unassigned;
183+
inherited;
184+
end;
185+
186+
function TWMIInstance.GetName: string;
187+
begin
188+
Result := fInstance;
189+
end;
190+
191+
function TWMIInstance.GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
192+
var
193+
prop : string;
194+
begin
195+
Result := TxList<TFlexPair>.Create;
196+
for prop in aProperties do
197+
begin
105198
try
106-
objWMIService := GetObject(Format('winmgmts:\\%s\%s',[aWMIHost,aRoot]));
107-
colItems := objWMIService.ExecQuery(Format('SELECT * FROM %s',[aWMIClass]),'WQL',0);
108-
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
109-
while oEnum.Next(1, colItem, iValue) = 0 do
110-
begin
111-
Result := colItem.Properties_.Item(aWMIProperty, 0);
112-
Break;
113-
end;
199+
Result.Add(TFlexPair.Create(prop,fWMIItem.Properties_.Item(prop, 0)));
114200
except
115-
on E : Exception do raise EWMICollector.CreateFmt('Error getting WMI property: %s',[e.Message]);
201+
on E : Exception do raise EWMICollector.CreateFmt('Retrieving "%s" (%s)',[prop,e.message]);
116202
end;
117-
finally
118-
CoUninitialize;
119203
end;
120204
end;
121205

122-
class function TWMICollector.GetPropertyInstances(const aWMIHost, aRoot, aWMIClass,aWMIProperty : string; const aInstances : string = '*') : TFlexPairArray;
206+
function TWMIInstance.GetProperty(const aPropertyName: string): TFlexValue;
207+
begin
208+
Result := fWMIItem.Properties_.Item(aPropertyName, 0);
209+
end;
210+
211+
{ TWMIClass }
212+
213+
constructor TWMIClass.Create(aWMIService : OleVariant; const aClassName : string; aWMIClassItems : IEnumvariant);
214+
begin
215+
fWMIService := aWMIService;
216+
fClassName := aClassName;
217+
fWMIClassItems := aWMIClassItems;
218+
end;
219+
220+
destructor TWMIClass.Destroy;
221+
begin
222+
//fWMIClassItems := nil;
223+
fWMIService := Unassigned;
224+
inherited;
225+
end;
226+
227+
function TWMIClass.GetInstance(const aInstance: string): IWMIInstance;
123228
var
124-
objWMIService : OLEVariant;
125-
colItems : OLEVariant;
126-
colItem : OLEVariant;
127-
oEnum : IEnumvariant;
229+
propItem : OLEVariant;
128230
iValue : LongWord;
231+
instanceName : string;
129232
begin
130-
CoInitialize(nil);
131-
try
233+
while fWMIClassItems.Next(1, propItem, iValue) = 0 do
234+
begin
235+
instanceName := GetInstanceName(propItem);
132236
try
133-
objWMIService := GetObject(Format('winmgmts:\\%s\%s',[aWMIHost,aRoot]));
134-
colItems := objWMIService.ExecQuery(Format('SELECT * FROM %s',[aWMIClass]),'WQL',0);
135-
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
136-
while oEnum.Next(1, colItem, iValue) = 0 do
237+
if CompareText(aInstance,instanceName) = 0 then
137238
begin
138-
if (aInstances = '*') or (CompareText(aInstances,colItem.Name) = 0) then
139-
begin
140-
Result.Add(colItem.Name,colItem.Properties_.Item(aWMIProperty, 0));
141-
end;
239+
Result := TWMIInstance.Create(instanceName,propItem);
240+
Break;
142241
end;
143-
except
144-
on E : Exception do raise EWMICollector.CreateFmt('Error getting WMI property: %s',[e.Message]);
242+
finally
243+
propItem := Unassigned;
244+
end;
245+
end;
246+
end;
247+
248+
function TWMIClass.GetInstanceName(aWMIClass : OleVariant) : string;
249+
var
250+
qualifiers : OleVariant;
251+
enumQualif : IEnumVariant;
252+
qualifItem : OleVariant;
253+
pceltFetched : Cardinal;
254+
propItem : OleVariant;
255+
enumProp : IEnumVariant;
256+
iValue : Cardinal;
257+
properties : OleVariant;
258+
objSWbemObjectSet : OleVariant;
259+
begin
260+
Result := '';
261+
objSWbemObjectSet:= fWMIService.Get(fClassName, wbemFlagUseAmendedQualifiers and wbemFlagReturnWhenComplete);
262+
properties := objSWbemObjectSet.Properties_;
263+
enumProp := IUnknown(properties._NewEnum) as IENumVariant;
264+
while enumProp.Next(1, propItem, iValue) = 0 do
265+
begin
266+
qualifiers := propItem.Qualifiers_;
267+
enumQualif := IUnknown(qualifiers._NewEnum) as IEnumVariant;
268+
//iterate over the qualifiers
269+
while enumQualif.Next(1, qualifItem, pceltFetched) = 0 do
270+
begin
271+
//check the name of the qualifier
272+
//Result := rgvarQualif.Name;
273+
//Result := rgvarQualif.Value;
274+
if qualifItem.Name = 'key' then
275+
begin
276+
if qualifItem.Value then if Result = '' then Result := aWMIClass.Properties_.Item(propItem.Name,0)
277+
else Result := Format('%s %s',[Result,aWMIClass.Properties_.Item(propItem.Name,0)]);
278+
end;
279+
//VarClear(qualifItem);
280+
qualifItem := Unassigned;
281+
end;
282+
//enumQualif := nil;
283+
qualifiers := Unassigned;
284+
propItem := Unassigned;
285+
end;
286+
//enumProp := nil;
287+
properties := Unassigned;
288+
objSWbemObjectSet := Unassigned;
289+
end;
290+
291+
function TWMIClass.GetInstances(const aInstances: TArray<string>): TWMIInstances;
292+
var
293+
propItem : OLEVariant;
294+
iValue : LongWord;
295+
getAllInstances : Boolean;
296+
instanceName : string;
297+
begin
298+
getAllInstances := (High(aInstances) = 0) and (aInstances[0] = '*');
299+
while fWMIClassItems.Next(1, propItem, iValue) = 0 do
300+
begin
301+
instanceName := GetInstanceName(propItem);
302+
if (getAllInstances) or (StrInArray(instancename,aInstances)) then
303+
begin
304+
Result := Result + [TWMIInstance.Create(instanceName,propItem)];
145305
end;
146-
finally
147-
CoUninitialize;
306+
propItem := Unassigned;
148307
end;
149308
end;
150309

0 commit comments

Comments
 (0)