Iterating over SWbemPropertySet objects
Asked Answered
B

2

5

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?

Bamberg answered 4/12, 2013 at 21:55 Comment(2)
Which language are you using to access the WMI?Olenolin
I'm using Go.Bamberg
O
8

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.

Olenolin answered 5/12, 2013 at 2:34 Comment(0)
T
0

You need to query the object class to get all the properties. Here's an example where the object class properties are used to convert a WMI query to a stringified JSON object.

function getWMIObjectJSON(strNameSpace,strClass,strFilter)
    strComputer = "." 
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
            strComputer & "\" & strNameSpace)
    Set objClass = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
            strComputer & "\" & strNameSpace & ":" & strClass)      
    colCount=0
    rtn="{""description"":""" & escStr(strNameSpace & ":" & strClass & " " & strFilter) & """,""title"":""" & _
            escStr(strNameSpace & ":" & strClass) & """,""columns"":["  
    For Each objClassProperty In objClass.Properties_       
        if colCount>0 then rtn=rtn & ","
        rtn=rtn & """" & escStr(objClassProperty.Name) & """"
        colCount=colCount + 1
    Next    
    Set colData = objWMIService.ExecQuery("Select * from " & strClass & " " & strFilter)        
    rtn=rtn & "],""record_count"":" & colData.Count & ",""records"":["
    rowCount=0
    For Each objData In colData
        if rowCount > 0 then rtn=rtn & ","
        rtn=rtn & "{"
        colCount=0
        For Each objClassProperty In objClass.Properties_ 
            if colCount > 0 then rtn=rtn & ","
            rtn=rtn & """" & escStr(objClassProperty.Name) & """:""" & _
                    escStr(objData.Properties_(objClassProperty.Name).Value) & """"
            colCount=colCount + 1
        Next
        rtn=rtn & "}"
        rowCount=rowCount + 1
    Next    
    rtn=rtn & "]}"
    getWMIObjectJSON = rtn
end function

desktop = getWMIObjectJSON("root\cimv2","Win32_Desktop","where Name like '%u%'")
WScript.Echo desktop
<package>
<job id="wmiExample">
   <script language="VBScript" src="wmi.vbs"/>     
   <script language="JScript">     
      var desktop = eval("(" + getWMIObjectJSON("root\cimv2","Win32_Desktop","") + ")");
      for(d in desktop.records){
        WScript.Echo(desktop.records[d].Name);
      }
   </script>
</job>
</package>
Tother answered 23/2, 2022 at 22:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.