Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over SWbemPropertySet objects

Tags:

com

wmi

A WQL query in WMI using the COM API returns a SWbemObjectSet. From this, we can use the ItemIndex method to iterate over all objects in the set, resulting in many SWbemObjects. These have a Properties_ property, which returns a SWbemPropertySet.

This object has a Count property, but no ItemIndex method, instead only an Item method, which takes a string name of the property to fetch. I'd like to iterate over all available properties, thus I don't have the name available. I've tried calling an ItemIndex method, but (as per the documentation) it does not exist on this object. There are many VBScript documents around that do something like For Each prop in object.Properties_, so I assume this is somehow possible.

How can I find all properties?

like image 694
mjibson Avatar asked Dec 04 '13 21:12

mjibson


1 Answers

First, the ItemIndex property only exist in some versions of the Microsoft WMI Scripting Library you can find more info about this topic on this article which I wrote some time ago Be careful when you import the Microsoft WMI Scripting Library (The code uses Delphi but the same applies to any language using this Library).

Now to iterate over the elements of an SWbemPropertySet you must get a instance to the enumerator accessing the _NewEnum property which provides a method for enumerating a collection of variants using the IEnumVARIANT interface. This is done automagically by vbscript, but in others languages like Delphi or C++ must be done manually.

Try this Delphi sample

{$APPTYPE CONSOLE}    

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants,
  WbemScripting_TLB in 'WbemScripting_TLB.pas';

procedure ShowProperties(const WMINameSpace, WMIClass : string);
var
  WMIServices     : ISWbemServices;
  SWbemObjectSet  : ISWbemObjectSet;
  SObject         : ISWbemObject;
  LProperty       : ISWbemProperty;
  Enum, Enum2     : IEnumVariant;
  TempObj, TempObj2: OleVariant;
  Value           : Cardinal;
  SWbemPropertySet: ISWbemPropertySet;
begin
  WMIServices := CoSWbemLocator.Create.ConnectServer('.', WMINameSpace,'', '', '', '', 0, nil);
  SWbemObjectSet := WMIServices.ExecQuery(Format('Select * FROM %s',[WMIClass]), 'WQL', 0, nil);
  Enum := (SWbemObjectSet._NewEnum) as IEnumVariant;
  if (Enum.Next(1, TempObj, Value) = S_OK) then
  begin
    SObject     := IUnknown(TempObj) as ISWBemObject;
    SWbemPropertySet := SObject.Properties_;
    Enum2 := (SWbemPropertySet._NewEnum) as IEnumVariant;
    while (Enum2.Next(1, TempObj2, Value) = S_OK) do
    begin
      LProperty     := IUnknown(TempObj2) as ISWbemProperty;
      Writeln(LProperty.Name);
      TempObj2:=Unassigned;
    end;
    TempObj:=Unassigned;
  end;
end;

begin
 try
    CoInitialize(nil);
    try
      ShowProperties('root\cimv2','Win32_BaseBoard');
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.

I hope which you can translate this sample to the Go language.

like image 186
RRUZ Avatar answered Sep 20 '22 01:09

RRUZ