Search code examples
delphiwmiwmi-queryenumerate

How do I get the names of the columns returned by a WbemScripting query?


I have the following procedure to run a WMI query, and it works perfectly well.

procedure TFormMain.GetWMIOSInfo(const RemoteMachine, Username, Password: string);
var
  FSWbemLocator: OLEVariant;
  FWMIService: OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject: OLEVariant;
  oEnum: IEnumvariant;
  iValue: LongWord;
begin;
  try
    FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
    FWMIService := FSWbemLocator.ConnectServer(RemoteMachine, 'root\CIMV2', Username, Password);
    FWbemObjectSet := FWMIService.ExecQuery(
        'select screenwidth, screenheight, status from Win32_DesktopMonitor','WQL', 0);
    try
      oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
      while oEnum.Next(1, FWbemObject, iValue) = 0 do
        begin
          Listbox1.Items.Add(
            VarToStr(FWbemObject.availability) + ', ' + 
            VarToStr(FWbemObject.screenwidth)  + ', ' +
            VarToStr(FWbemObject.screenheight));

          FWbemObject := Unassigned;
        end;

    finally
      FWbemObjectSet := Unassigned;
    end;

  Except on E: Exception do
    Raise;
  end;
end;

I would like to alter the query to return all the fields like select * from Win32_DesktopMonitor. My problem is that I do not know how to determine the names of the columns that are returned by the query in FWbemObject. ie. I'd like to enumerate the columns in the FWbemObject.

Listbox1.Items.Add(
  VarToStr(FWbemObject.<?>) + ', ' + 
  VarToStr(FWbemObject.<?>)  + ', ' +
  ....
  VarToStr(FWbemObject.<?>));

Solution

  • Pieter you must use the SWbemObject.Properties_ Property of the SWbemObject Object.

    check this sample.

    program GetWMI_Info;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils,
      ActiveX,
      ComObj,
      Variants;
    
    
    procedure  GetWin32_DesktopMonitorInfo;
    var
      FSWbemLocator : OLEVariant;
      FWMIService   : OLEVariant;
      FWbemObjectSet: OLEVariant;
      FWbemObject   : OLEVariant;
      oEnum         : IEnumvariant;
      iValue        : LongWord;
    
      FProperties   : OLEVariant;
      oEnumProp     : IEnumvariant;
      iValueProp    : LongWord;
      FPropObj      : OLEVariant;
    begin;
      FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
      FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
      FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_DesktopMonitor','WQL',0);
      oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
      if oEnum.Next(1, FWbemObject, iValue) = 0 then
      begin
    
        FProperties   := FWbemObject.Properties_;
        oEnumProp     := IUnknown(FProperties._NewEnum) as IEnumVariant;
        while oEnumProp.Next(1, FPropObj, iValueProp) = 0 do
        begin
           Writeln(FPropObj.Name);
           FPropObj:=Unassigned; //prevent memory leak
        end;
    
        FWbemObject:=Unassigned;//prevent memory leak
      end;
    end;
    
    
    begin
     try
        CoInitialize(nil);
        try
          GetWin32_DesktopMonitorInfo;
          Readln;
        finally
        CoUninitialize;
        end;
     except
        on E:Exception do
        begin
            Writeln(E.Classname, ':', E.Message);
            Readln;
        end;
      end;
    end.