Quick.WMI.pas 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. { ***************************************************************************
  2. Copyright (c) 2016-2020 Kike Pérez
  3. Unit : Quick.WMI
  4. Description : Common functions
  5. Author : Kike Pérez
  6. Version : 1.1
  7. Created : 04/04/2019
  8. Modified : 22/04/2020
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.WMI;
  22. {$i QuickLib.inc}
  23. {$TYPEDADDRESS OFF}
  24. {$WARN SYMBOL_PLATFORM OFF}
  25. {$WRITEABLECONST ON}
  26. {$VARPROPSETTER ON}
  27. interface
  28. uses
  29. SysUtils,
  30. ActiveX,
  31. ComObj,
  32. Quick.Commons,
  33. Quick.Collections,
  34. Quick.Arrays,
  35. Quick.Value,
  36. Variants;
  37. type
  38. IWMIInstance = interface
  39. ['{4C81A6A6-4A65-46FB-B05B-5898DF51F9B7}']
  40. function GetProperty(const aPropertyName : string) : TFlexValue;
  41. function GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
  42. function GetName : string;
  43. end;
  44. TWMIInstance = class(TInterfacedObject,IWMIInstance)
  45. private
  46. fInstance : string;
  47. fWMIItem : OleVariant;
  48. public
  49. constructor Create(const aInstanceName : string; aWMIItem: OleVariant);
  50. destructor Destroy; override;
  51. function GetProperty(const aPropertyName : string) : TFlexValue;
  52. function GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
  53. function GetName : string;
  54. end;
  55. TWMIInstances = TArray<IWMIInstance>;
  56. IWMIClass = interface
  57. ['{FAFE26ED-28BC-4591-AE5A-9E4543074B5C}']
  58. function GetInstance(const aInstance : string) : IWMIInstance;
  59. function GetInstances(const aInstances : TArray<string>) : TWMIInstances;
  60. end;
  61. TWMIClass = class(TInterfacedObject,IWMIClass)
  62. private
  63. fClassName : string;
  64. fWMIService : OleVariant;
  65. fWMIClassItems : IEnumvariant;
  66. function GetInstanceName(aWMIClass : OleVariant) : string;
  67. public
  68. constructor Create(aWMIService : OleVariant; const aClassName : string; aWMIClassItems : IEnumvariant);
  69. destructor Destroy; override;
  70. function GetInstance(const aInstance : string) : IWMIInstance;
  71. function GetInstances(const aInstances : TArray<string>) : TWMIInstances;
  72. end;
  73. IWMICollector = interface
  74. ['{3FFFF0DC-F533-4FE1-A511-73E76EC6BCC8}']
  75. function From(const aRoot, aWMIClass : string) : IWMIClass; overload;
  76. function From(const aHost, aRoot, aWMIClass : string) : IWMIClass; overload;
  77. end;
  78. TWMICollector = class(TInterfacedObject,IWMICollector)
  79. private
  80. fNamespace : string;
  81. fWMIService : OleVariant;
  82. public
  83. constructor Create;
  84. destructor Destroy; override;
  85. class function GetObject(const aObjectName: string) : IDispatch;
  86. function From(const aRoot, aWMIClass : string) : IWMIClass; overload;
  87. function From(const aHost, aRoot, aWMIClass : string) : IWMIClass; overload;
  88. end;
  89. EWMICollector = class(Exception);
  90. implementation
  91. const
  92. wbemFlagUseAmendedQualifiers = $00020000;
  93. wbemFlagReturnImmediately = $00000010;
  94. wbemFlagReturnWhenComplete = $00000000;
  95. wbemFlagForwardOnly = $00000020;
  96. { TWMICollector }
  97. constructor TWMICollector.Create;
  98. begin
  99. fNamespace := '';
  100. CoInitialize(nil);
  101. end;
  102. destructor TWMICollector.Destroy;
  103. begin
  104. fWMIService := Unassigned;
  105. CoUninitialize;
  106. inherited;
  107. end;
  108. class function TWMICollector.GetObject(const aObjectName: string) : IDispatch;
  109. var
  110. chEaten : Integer;
  111. bindCtx : IBindCtx;
  112. moniker : IMoniker;
  113. begin
  114. OleCheck(CreateBindCtx(0, bindCtx));
  115. OleCheck(MkParseDisplayName(bindCtx, PWideChar(aObjectName), chEaten, moniker));
  116. OleCheck(Moniker.BindToObject(bindCtx, nil, IDispatch, Result));
  117. end;
  118. function TWMICollector.From(const aRoot, aWMIClass : string) : IWMIClass;
  119. begin
  120. Result := From('.',aRoot,aWMIClass);
  121. end;
  122. function TWMICollector.From(const aHost, aRoot, aWMIClass : string) : IWMIClass;
  123. var
  124. colItems : OLEVariant;
  125. oEnum : IEnumvariant;
  126. begin
  127. try
  128. //only connect if namespace is different from previous connection
  129. if fNamespace <> aHost + '\' + aRoot then
  130. begin
  131. fWMIService := GetObject(Format('winmgmts:\\%s\%s',[aHost,aRoot]));
  132. fNamespace := aHost + '\' + aRoot;
  133. end;
  134. colItems := fWMIService.ExecQuery(Format('SELECT * FROM %s',[aWMIClass]),'WQL',wbemFlagForwardOnly and wbemFlagReturnImmediately);
  135. oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
  136. Result := TWMIClass.Create(fWMIService,aWMIClass,oEnum);
  137. oEnum := nil;
  138. colItems := Unassigned;
  139. except
  140. on E : Exception do raise EWMICollector.CreateFmt('Error getting WMI Class "\\%s\%s\%s": %s',[aHost,aRoot,aWMIClass,e.Message]);
  141. end;
  142. end;
  143. { TWMIInstance }
  144. constructor TWMIInstance.Create(const aInstanceName : string; aWMIItem: OleVariant);
  145. begin
  146. fInstance := aInstanceName;
  147. fWMIItem := aWMIItem;
  148. end;
  149. destructor TWMIInstance.Destroy;
  150. begin
  151. fWMIItem := Unassigned;
  152. inherited;
  153. end;
  154. function TWMIInstance.GetName: string;
  155. begin
  156. Result := fInstance;
  157. end;
  158. function TWMIInstance.GetProperties(const aProperties : TArray<string>) : IList<TFlexPair>;
  159. var
  160. prop : string;
  161. item : OleVariant;
  162. begin
  163. Result := TxList<TFlexPair>.Create;
  164. for prop in aProperties do
  165. begin
  166. try
  167. item := fWMIItem.Properties_.Item(prop, 0);
  168. try
  169. Result.Add(TFlexPair.Create(prop,item));
  170. finally
  171. item := Unassigned;
  172. end;
  173. except
  174. on E : Exception do raise EWMICollector.CreateFmt('Retrieving "%s" (%s)',[prop,e.message]);
  175. end;
  176. end;
  177. end;
  178. function TWMIInstance.GetProperty(const aPropertyName: string): TFlexValue;
  179. var
  180. item : OleVariant;
  181. begin
  182. item := fWMIItem.Properties_.Item(aPropertyName, 0);
  183. try
  184. Result := item;
  185. finally
  186. item := Unassigned;
  187. end;
  188. end;
  189. { TWMIClass }
  190. constructor TWMIClass.Create(aWMIService : OleVariant; const aClassName : string; aWMIClassItems : IEnumvariant);
  191. begin
  192. fWMIService := aWMIService;
  193. fClassName := aClassName;
  194. fWMIClassItems := aWMIClassItems;
  195. end;
  196. destructor TWMIClass.Destroy;
  197. begin
  198. fWMIClassItems := nil;
  199. fWMIService := Unassigned;
  200. inherited;
  201. end;
  202. function TWMIClass.GetInstance(const aInstance: string): IWMIInstance;
  203. var
  204. propItem : OLEVariant;
  205. iValue : LongWord;
  206. instanceName : string;
  207. begin
  208. while fWMIClassItems.Next(1, propItem, iValue) = 0 do
  209. begin
  210. try
  211. instanceName := GetInstanceName(propItem);
  212. if CompareText(aInstance,instanceName) = 0 then
  213. begin
  214. Result := TWMIInstance.Create(instanceName,propItem);
  215. Break;
  216. end;
  217. finally
  218. propItem := Unassigned;
  219. end;
  220. end;
  221. end;
  222. function TWMIClass.GetInstanceName(aWMIClass : OleVariant) : string;
  223. var
  224. qualifiers : OleVariant;
  225. enumQualif : IEnumVariant;
  226. qualifItem : OleVariant;
  227. pceltFetched : Cardinal;
  228. propItem : OleVariant;
  229. enumProp : IEnumVariant;
  230. iValue : Cardinal;
  231. properties : OleVariant;
  232. objSWbemObjectSet : OleVariant;
  233. item : OleVariant;
  234. begin
  235. Result := '';
  236. objSWbemObjectSet:= fWMIService.Get(fClassName, wbemFlagUseAmendedQualifiers and wbemFlagReturnWhenComplete);
  237. properties := objSWbemObjectSet.Properties_;
  238. enumProp := IUnknown(properties._NewEnum) as IENumVariant;
  239. while enumProp.Next(1, propItem, iValue) = 0 do
  240. begin
  241. qualifiers := propItem.Qualifiers_;
  242. enumQualif := IUnknown(qualifiers._NewEnum) as IEnumVariant;
  243. //iterate over the qualifiers
  244. while enumQualif.Next(1, qualifItem, pceltFetched) = 0 do
  245. begin
  246. //check the name of the qualifier
  247. //Result := rgvarQualif.Name;
  248. //Result := rgvarQualif.Value;
  249. if qualifItem.Name = 'key' then
  250. begin
  251. item := aWMIClass.Properties_.Item(propItem.Name,0);
  252. try
  253. if qualifItem.Value then if Result = '' then Result := item
  254. else Result := Format('%s %s',[Result,item]);
  255. finally
  256. item := Unassigned;
  257. end;
  258. end;
  259. qualifItem := Unassigned;
  260. end;
  261. enumQualif := nil;
  262. qualifiers := Unassigned;
  263. propItem := Unassigned;
  264. end;
  265. enumProp := nil;
  266. properties := Unassigned;
  267. objSWbemObjectSet := Unassigned;
  268. end;
  269. function TWMIClass.GetInstances(const aInstances: TArray<string>): TWMIInstances;
  270. var
  271. propItem : OLEVariant;
  272. iValue : LongWord;
  273. getAllInstances : Boolean;
  274. instanceName : string;
  275. begin
  276. getAllInstances := (High(aInstances) = 0) and (aInstances[0] = '*');
  277. while fWMIClassItems.Next(1, propItem, iValue) = 0 do
  278. begin
  279. instanceName := GetInstanceName(propItem);
  280. if (getAllInstances) or (StrInArray(instancename,aInstances)) then
  281. begin
  282. Result := Result + [TWMIInstance.Create(instanceName,propItem)];
  283. end;
  284. propItem := Unassigned;
  285. end;
  286. end;
  287. end.