|
@@ -1,13 +1,13 @@
|
|
|
{ ***************************************************************************
|
|
|
|
|
|
- Copyright (c) 2016-2019 Kike Pérez
|
|
|
+ Copyright (c) 2016-2020 Kike Pérez
|
|
|
|
|
|
Unit : Quick.WMI
|
|
|
Description : Common functions
|
|
|
Author : Kike Pérez
|
|
|
- Version : 1.0
|
|
|
+ Version : 1.1
|
|
|
Created : 04/04/2019
|
|
|
- Modified : 08/04/2019
|
|
|
+ Modified : 22/04/2020
|
|
|
|
|
|
This file is part of QuickLib: https://github.com/exilon/QuickLib
|
|
|
|
|
@@ -40,47 +40,99 @@ interface
|
|
|
|
|
|
uses
|
|
|
SysUtils,
|
|
|
- WbemScripting_TLB,
|
|
|
ActiveX,
|
|
|
ComObj,
|
|
|
+ Quick.Commons,
|
|
|
+ Quick.Collections,
|
|
|
Quick.Arrays,
|
|
|
Quick.Value,
|
|
|
Variants;
|
|
|
|
|
|
type
|
|
|
|
|
|
- TFlexArray = TArray<TFlexValue>;
|
|
|
+ IWMIInstance = interface
|
|
|
+ ['{4C81A6A6-4A65-46FB-B05B-5898DF51F9B7}']
|
|
|
+ function GetProperty(const aPropertyName : string) : TFlexValue;
|
|
|
+ function GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
|
|
|
+ function GetName : string;
|
|
|
+ end;
|
|
|
|
|
|
- TWMIObject = record
|
|
|
+ TWMIInstance = class(TInterfacedObject,IWMIInstance)
|
|
|
private
|
|
|
fInstance : string;
|
|
|
- fProperty : string;
|
|
|
+ fWMIItem : OleVariant;
|
|
|
+ public
|
|
|
+ constructor Create(const aInstanceName : string; aWMIItem: OleVariant);
|
|
|
+ destructor Destroy; override;
|
|
|
+ function GetProperty(const aPropertyName : string) : TFlexValue;
|
|
|
+ function GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
|
|
|
+ function GetName : string;
|
|
|
end;
|
|
|
|
|
|
- TWMICollector = class
|
|
|
- private
|
|
|
- class function GetObject(const aObjectName: string) : IDispatch;
|
|
|
- public
|
|
|
- class function GetProperty(const aWMIHost, aRoot, aWMIClass, aWMIProperty : string) : TFlexValue;
|
|
|
- class function GetPropertyInstances(const aWMIHost, aRoot, aWMIClass,aWMIProperty : string; const aInstances : string = '*') : TFlexPairArray;
|
|
|
+ TWMIInstances = TArray<IWMIInstance>;
|
|
|
+
|
|
|
+ IWMIClass = interface
|
|
|
+ ['{FAFE26ED-28BC-4591-AE5A-9E4543074B5C}']
|
|
|
+ function GetInstance(const aInstance : string) : IWMIInstance;
|
|
|
+ function GetInstances(const aInstances : TArray<string>) : TWMIInstances;
|
|
|
end;
|
|
|
|
|
|
- TWMIInstance = class
|
|
|
+ TWMIClass = class(TInterfacedObject,IWMIClass)
|
|
|
private
|
|
|
- fInstance : string;
|
|
|
+ fClassName : string;
|
|
|
+ fWMIService : OleVariant;
|
|
|
+ fWMIClassItems : IEnumvariant;
|
|
|
+ function GetInstanceName(aWMIClass : OleVariant) : string;
|
|
|
public
|
|
|
- property Instance :
|
|
|
+ constructor Create(aWMIService : OleVariant; const aClassName : string; aWMIClassItems : IEnumvariant);
|
|
|
+ destructor Destroy; override;
|
|
|
+ function GetInstance(const aInstance : string) : IWMIInstance;
|
|
|
+ function GetInstances(const aInstances : TArray<string>) : TWMIInstances;
|
|
|
end;
|
|
|
|
|
|
- TWMIObject2 = class
|
|
|
+ IWMICollector = interface
|
|
|
+ ['{3FFFF0DC-F533-4FE1-A511-73E76EC6BCC8}']
|
|
|
+ function From(const aRoot, aWMIClass : string) : IWMIClass; overload;
|
|
|
+ function From(const aHost, aRoot, aWMIClass : string) : IWMIClass; overload;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TWMICollector = class(TInterfacedObject,IWMICollector)
|
|
|
+ private
|
|
|
+ fNamespace : string;
|
|
|
+ fWMIService : OleVariant;
|
|
|
public
|
|
|
- function FromInstance(const aInstanceName : string) : TWMIInstance;
|
|
|
+ constructor Create;
|
|
|
+ destructor Destroy; override;
|
|
|
+ class function GetObject(const aObjectName: string) : IDispatch;
|
|
|
+ function From(const aRoot, aWMIClass : string) : IWMIClass; overload;
|
|
|
+ function From(const aHost, aRoot, aWMIClass : string) : IWMIClass; overload;
|
|
|
end;
|
|
|
|
|
|
EWMICollector = class(Exception);
|
|
|
|
|
|
implementation
|
|
|
|
|
|
+const
|
|
|
+ wbemFlagUseAmendedQualifiers = $00020000;
|
|
|
+ wbemFlagReturnImmediately = $00000010;
|
|
|
+ wbemFlagReturnWhenComplete = $00000000;
|
|
|
+ wbemFlagForwardOnly = $00000020;
|
|
|
+
|
|
|
+{ TWMICollector }
|
|
|
+
|
|
|
+constructor TWMICollector.Create;
|
|
|
+begin
|
|
|
+ fNamespace := '';
|
|
|
+ CoInitialize(nil);
|
|
|
+end;
|
|
|
+
|
|
|
+destructor TWMICollector.Destroy;
|
|
|
+begin
|
|
|
+ fWMIService := Unassigned;
|
|
|
+ CoUninitialize;
|
|
|
+ inherited;
|
|
|
+end;
|
|
|
+
|
|
|
class function TWMICollector.GetObject(const aObjectName: string) : IDispatch;
|
|
|
var
|
|
|
chEaten : Integer;
|
|
@@ -92,59 +144,166 @@ begin
|
|
|
OleCheck(Moniker.BindToObject(bindCtx, nil, IDispatch, Result));
|
|
|
end;
|
|
|
|
|
|
-class function TWMICollector.GetProperty(const aWMIHost, aRoot, aWMIClass, aWMIProperty: string) : TFlexValue;
|
|
|
+function TWMICollector.From(const aRoot, aWMIClass : string) : IWMIClass;
|
|
|
+begin
|
|
|
+ Result := From('.',aRoot,aWMIClass);
|
|
|
+end;
|
|
|
+
|
|
|
+function TWMICollector.From(const aHost, aRoot, aWMIClass : string) : IWMIClass;
|
|
|
var
|
|
|
- objWMIService : OLEVariant;
|
|
|
colItems : OLEVariant;
|
|
|
- colItem : OLEVariant;
|
|
|
oEnum : IEnumvariant;
|
|
|
- iValue : LongWord;
|
|
|
begin
|
|
|
- CoInitialize(nil);
|
|
|
try
|
|
|
+ //only connect if namespace is different from previous connection
|
|
|
+ if fNamespace <> aHost + '\' + aRoot then
|
|
|
+ begin
|
|
|
+ fWMIService := GetObject(Format('winmgmts:\\%s\%s',[aHost,aRoot]));
|
|
|
+ fNamespace := aHost + '\' + aRoot;
|
|
|
+ end;
|
|
|
+ colItems := fWMIService.ExecQuery(Format('SELECT * FROM %s',[aWMIClass]),'WQL',wbemFlagForwardOnly and wbemFlagReturnImmediately);
|
|
|
+ oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
|
|
|
+ Result := TWMIClass.Create(fWMIService,aWMIClass,oEnum);
|
|
|
+ except
|
|
|
+ on E : Exception do raise EWMICollector.CreateFmt('Error getting WMI Class "\\%s\%s\%s": %s',[aHost,aRoot,aWMIClass,e.Message]);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+{ TWMIInstance }
|
|
|
+
|
|
|
+constructor TWMIInstance.Create(const aInstanceName : string; aWMIItem: OleVariant);
|
|
|
+begin
|
|
|
+ fInstance := aInstanceName;
|
|
|
+ fWMIItem := aWMIItem;
|
|
|
+end;
|
|
|
+
|
|
|
+destructor TWMIInstance.Destroy;
|
|
|
+begin
|
|
|
+ fWMIItem := Unassigned;
|
|
|
+ inherited;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWMIInstance.GetName: string;
|
|
|
+begin
|
|
|
+ Result := fInstance;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWMIInstance.GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
|
|
|
+var
|
|
|
+ prop : string;
|
|
|
+begin
|
|
|
+ Result := TxList<TFlexPair>.Create;
|
|
|
+ for prop in aProperties do
|
|
|
+ begin
|
|
|
try
|
|
|
- objWMIService := GetObject(Format('winmgmts:\\%s\%s',[aWMIHost,aRoot]));
|
|
|
- colItems := objWMIService.ExecQuery(Format('SELECT * FROM %s',[aWMIClass]),'WQL',0);
|
|
|
- oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
|
|
|
- while oEnum.Next(1, colItem, iValue) = 0 do
|
|
|
- begin
|
|
|
- Result := colItem.Properties_.Item(aWMIProperty, 0);
|
|
|
- Break;
|
|
|
- end;
|
|
|
+ Result.Add(TFlexPair.Create(prop,fWMIItem.Properties_.Item(prop, 0)));
|
|
|
except
|
|
|
- on E : Exception do raise EWMICollector.CreateFmt('Error getting WMI property: %s',[e.Message]);
|
|
|
+ on E : Exception do raise EWMICollector.CreateFmt('Retrieving "%s" (%s)',[prop,e.message]);
|
|
|
end;
|
|
|
- finally
|
|
|
- CoUninitialize;
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
-class function TWMICollector.GetPropertyInstances(const aWMIHost, aRoot, aWMIClass,aWMIProperty : string; const aInstances : string = '*') : TFlexPairArray;
|
|
|
+function TWMIInstance.GetProperty(const aPropertyName: string): TFlexValue;
|
|
|
+begin
|
|
|
+ Result := fWMIItem.Properties_.Item(aPropertyName, 0);
|
|
|
+end;
|
|
|
+
|
|
|
+{ TWMIClass }
|
|
|
+
|
|
|
+constructor TWMIClass.Create(aWMIService : OleVariant; const aClassName : string; aWMIClassItems : IEnumvariant);
|
|
|
+begin
|
|
|
+ fWMIService := aWMIService;
|
|
|
+ fClassName := aClassName;
|
|
|
+ fWMIClassItems := aWMIClassItems;
|
|
|
+end;
|
|
|
+
|
|
|
+destructor TWMIClass.Destroy;
|
|
|
+begin
|
|
|
+ //fWMIClassItems := nil;
|
|
|
+ fWMIService := Unassigned;
|
|
|
+ inherited;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWMIClass.GetInstance(const aInstance: string): IWMIInstance;
|
|
|
var
|
|
|
- objWMIService : OLEVariant;
|
|
|
- colItems : OLEVariant;
|
|
|
- colItem : OLEVariant;
|
|
|
- oEnum : IEnumvariant;
|
|
|
+ propItem : OLEVariant;
|
|
|
iValue : LongWord;
|
|
|
+ instanceName : string;
|
|
|
begin
|
|
|
- CoInitialize(nil);
|
|
|
- try
|
|
|
+ while fWMIClassItems.Next(1, propItem, iValue) = 0 do
|
|
|
+ begin
|
|
|
+ instanceName := GetInstanceName(propItem);
|
|
|
try
|
|
|
- objWMIService := GetObject(Format('winmgmts:\\%s\%s',[aWMIHost,aRoot]));
|
|
|
- colItems := objWMIService.ExecQuery(Format('SELECT * FROM %s',[aWMIClass]),'WQL',0);
|
|
|
- oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
|
|
|
- while oEnum.Next(1, colItem, iValue) = 0 do
|
|
|
+ if CompareText(aInstance,instanceName) = 0 then
|
|
|
begin
|
|
|
- if (aInstances = '*') or (CompareText(aInstances,colItem.Name) = 0) then
|
|
|
- begin
|
|
|
- Result.Add(colItem.Name,colItem.Properties_.Item(aWMIProperty, 0));
|
|
|
- end;
|
|
|
+ Result := TWMIInstance.Create(instanceName,propItem);
|
|
|
+ Break;
|
|
|
end;
|
|
|
- except
|
|
|
- on E : Exception do raise EWMICollector.CreateFmt('Error getting WMI property: %s',[e.Message]);
|
|
|
+ finally
|
|
|
+ propItem := Unassigned;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWMIClass.GetInstanceName(aWMIClass : OleVariant) : string;
|
|
|
+var
|
|
|
+ qualifiers : OleVariant;
|
|
|
+ enumQualif : IEnumVariant;
|
|
|
+ qualifItem : OleVariant;
|
|
|
+ pceltFetched : Cardinal;
|
|
|
+ propItem : OleVariant;
|
|
|
+ enumProp : IEnumVariant;
|
|
|
+ iValue : Cardinal;
|
|
|
+ properties : OleVariant;
|
|
|
+ objSWbemObjectSet : OleVariant;
|
|
|
+begin
|
|
|
+ Result := '';
|
|
|
+ objSWbemObjectSet:= fWMIService.Get(fClassName, wbemFlagUseAmendedQualifiers and wbemFlagReturnWhenComplete);
|
|
|
+ properties := objSWbemObjectSet.Properties_;
|
|
|
+ enumProp := IUnknown(properties._NewEnum) as IENumVariant;
|
|
|
+ while enumProp.Next(1, propItem, iValue) = 0 do
|
|
|
+ begin
|
|
|
+ qualifiers := propItem.Qualifiers_;
|
|
|
+ enumQualif := IUnknown(qualifiers._NewEnum) as IEnumVariant;
|
|
|
+ //iterate over the qualifiers
|
|
|
+ while enumQualif.Next(1, qualifItem, pceltFetched) = 0 do
|
|
|
+ begin
|
|
|
+ //check the name of the qualifier
|
|
|
+ //Result := rgvarQualif.Name;
|
|
|
+ //Result := rgvarQualif.Value;
|
|
|
+ if qualifItem.Name = 'key' then
|
|
|
+ begin
|
|
|
+ if qualifItem.Value then if Result = '' then Result := aWMIClass.Properties_.Item(propItem.Name,0)
|
|
|
+ else Result := Format('%s %s',[Result,aWMIClass.Properties_.Item(propItem.Name,0)]);
|
|
|
+ end;
|
|
|
+ //VarClear(qualifItem);
|
|
|
+ qualifItem := Unassigned;
|
|
|
+ end;
|
|
|
+ //enumQualif := nil;
|
|
|
+ qualifiers := Unassigned;
|
|
|
+ propItem := Unassigned;
|
|
|
+ end;
|
|
|
+ //enumProp := nil;
|
|
|
+ properties := Unassigned;
|
|
|
+ objSWbemObjectSet := Unassigned;
|
|
|
+end;
|
|
|
+
|
|
|
+function TWMIClass.GetInstances(const aInstances: TArray<string>): TWMIInstances;
|
|
|
+var
|
|
|
+ propItem : OLEVariant;
|
|
|
+ iValue : LongWord;
|
|
|
+ getAllInstances : Boolean;
|
|
|
+ instanceName : string;
|
|
|
+begin
|
|
|
+ getAllInstances := (High(aInstances) = 0) and (aInstances[0] = '*');
|
|
|
+ while fWMIClassItems.Next(1, propItem, iValue) = 0 do
|
|
|
+ begin
|
|
|
+ instanceName := GetInstanceName(propItem);
|
|
|
+ if (getAllInstances) or (StrInArray(instancename,aInstances)) then
|
|
|
+ begin
|
|
|
+ Result := Result + [TWMIInstance.Create(instanceName,propItem)];
|
|
|
end;
|
|
|
- finally
|
|
|
- CoUninitialize;
|
|
|
+ propItem := Unassigned;
|
|
|
end;
|
|
|
end;
|
|
|
|