【问题标题】:Iterating over SWbemPropertySet objects迭代 SWbemPropertySet 对象
【发布时间】:2013-12-04 21:55:51
【问题描述】:

在 WMI 中使用 COM API 的 WQL 查询返回一个 SWbemObjectSet。由此,我们可以使用ItemIndex 方法遍历集合中的所有对象,从而产生许多SWbemObjects。它们有一个Properties_ 属性,它返回一个SWbemPropertySet

此对象有一个Count 属性,但没有ItemIndex 方法,而只有一个Item 方法,它接受要获取的属性的字符串名称。我想遍历所有可用的属性,因此我没有可用的名称。我试过调用ItemIndex 方法,但是(根据文档)它在这个对象上不存在。周围有许多 VBScript 文档会执行类似For Each prop in object.Properties_ 的操作,所以我认为这在某种程度上是可能的。

如何找到所有属性?

【问题讨论】:

  • 您使用哪种语言访问 WMI?
  • 我正在使用Go

标签: com wmi


【解决方案1】:

首先,ItemIndex 属性仅存在于Microsoft WMI Scripting Library 的某些版本中,您可以在我前段时间写的这篇文章中找到有关此主题的更多信息 Be careful when you import the Microsoft WMI Scripting Library(代码使用Delphi,但同样适用于使用此库的任何语言)。

现在要遍历SWbemPropertySet 的元素,您必须为访问_NewEnum 属性的枚举器获取一个实例,该属性提供了一种使用IEnumVARIANT 接口枚举变体集合的方法。这是由 vbscript自动完成的,但在其他语言(如 Delphi 或 C++)中必须手动完成。

试试这个 Delphi 示例

{$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.

我希望你能把这个示例翻译成 Go 语言。

【讨论】:

    【解决方案2】:

    您需要查询对象类以获取所有属性。这是一个使用对象类属性将 WMI 查询转换为字符串化 JSON 对象的示例。

    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>
    

    【讨论】:

      猜你喜欢
      • 2019-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      • 1970-01-01
      相关资源
      最近更新 更多