The Road to Delphi

Delphi – Free Pascal – Oxygene

WMI Delphi Code Creator – New Features

10 Comments

Update :  to get last version  check the new page of this project

Many new features was added to the application

The tool allows you compile and run the generated code directly without leaving the application

check the screen to select the installed Delphi compiler to use.

and the compiler result output

Added support for call WMI methods

Check the generated code for the Win32_Process wmi class and the Create method.

//------------------------------------------------------------------------------
//     This code was generated by the Wmi Delphi Code Creator https://theroadtodelphi.wordpress.com
//     Version: 1.0.0.11
//
//
//
//     LIABILITY DISCLAIMER
//     THIS GENERATED CODE IS DISTRIBUTED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.
//     YOU USE IT AT YOUR OWN RISK. THE AUTHOR NOT WILL BE LIABLE FOR DATA LOSS,
//     DAMAGES AND LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR MISUSING THIS CODE.
//
//
//------------------------------------------------------------------------------
program GetWMI_Info;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

function VarArrayToStr(const vArray: variant): string;

    function _VarToStr(const V: variant): string;
    var
    Vt: integer;
    begin
    Vt := VarType(V);
        case Vt of
          varSmallint,
          varInteger  : Result := IntToStr(integer(V));
          varSingle,
          varDouble,
          varCurrency : Result := FloatToStr(Double(V));
          varDate     : Result := VarToStr(V);
          varOleStr   : Result := WideString(V);
          varBoolean  : Result := VarToStr(V);
          varVariant  : Result := VarToStr(Variant(V));
          varByte     : Result := char(byte(V));
          varString   : Result := String(V);
          varArray    : Result := VarArrayToStr(Variant(V));
        end;
    end;

var
i : integer;
begin
    Result := '[';
     if (VarType(vArray) and VarArray)=0 then
       Result := _VarToStr(vArray)
    else
    for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do
     if i=VarArrayLowBound(vArray, 1)  then
      Result := Result+_VarToStr(vArray[i])
     else
      Result := Result+'|'+_VarToStr(vArray[i]);

    Result:=Result+']';
end;

function VarStrNull(const V:OleVariant):string; //avoid problems with null strings
begin
  Result:='';
  if not VarIsNull(V) then
  begin
    if VarIsArray(V) then
       Result:=VarArrayToStr(V)
    else
    Result:=VarToStr(V);
  end;
end;

function GetWMIObject(const objectName: String): IDispatch; //create the Wmi instance
var
  chEaten: Integer;
  BindCtx: IBindCtx;
  Moniker: IMoniker;
begin
  OleCheck(CreateBindCtx(0, bindCtx));
  OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
  OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
end;

//The Create method creates a new process.
//The method returns an integer value
//that can be interpretted as follows:
//0 - Successful completion.
//2 - The user
//does not have access to the requested information.
//3 - The user does not have
//sufficient privilge.
//8 - Unknown failure.
//9 - The path specified does not
//exist.
//21 - The specified parameter is invalid.
//Other - For integer values
//other than those listed above, refer to Win32 error code documentation.

procedure  Invoke_Win32_Process_Create;
var
  objWMIService   : OLEVariant;
  objInvoker      : OLEVariant;
  objInParams     : OLEVariant;
  objOutParams    : OLEVariant;
begin
  objWMIService := GetWMIObject(Format('winmgmts:\\%s\%s',['.','root\CIMV2']));
  objInvoker    := objWMIService.Get('Win32_Process');
  objInParams   := objInvoker.Methods_.Item('Create').InParameters.SpawnInstance_();
  objInParams.CommandLine:='notepad.exe';
  objOutParams  := objWMIService.ExecMethod('Win32_Process', 'Create', objInParams);
  Writeln('ProcessId           '+VarStrNull(objOutParams.ProcessId));
  Writeln('ReturnValue         '+VarStrNull(objOutParams.ReturnValue));
end;

begin
 try
    CoInitialize(nil);
    try
      Invoke_Win32_Process_Create;
      Readln;
    finally
    CoUninitialize;
    end;
 except
    on E:Exception do
    begin
        Writeln(E.Classname, ':', E.Message);
        Readln;
    end;
  end;
end.

Added support for WMI events

Check the generated code for the __InstanceCreationEvent Event using as traget instance the Win32_Process class, this sample code check when new process is launched in the whole system.

//------------------------------------------------------------------------------
//     This code was generated by the Wmi Delphi Code Creator https://theroadtodelphi.wordpress.com
//     Version: 1.0.0.11
//
//
//
//     LIABILITY DISCLAIMER
//     THIS GENERATED CODE IS DISTRIBUTED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.
//     YOU USE IT AT YOUR OWN RISK. THE AUTHOR NOT WILL BE LIABLE FOR DATA LOSS,
//     DAMAGES AND LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR MISUSING THIS CODE.
//
//
//------------------------------------------------------------------------------
program GetWMI_Info;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

function VarArrayToStr(const vArray: variant): string;

    function _VarToStr(const V: variant): string;
    var
    Vt: integer;
    begin
    Vt := VarType(V);
        case Vt of
          varSmallint,
          varInteger  : Result := IntToStr(integer(V));
          varSingle,
          varDouble,
          varCurrency : Result := FloatToStr(Double(V));
          varDate     : Result := VarToStr(V);
          varOleStr   : Result := WideString(V);
          varBoolean  : Result := VarToStr(V);
          varVariant  : Result := VarToStr(Variant(V));
          varByte     : Result := char(byte(V));
          varString   : Result := String(V);
          varArray    : Result := VarArrayToStr(Variant(V));
        end;
    end;

var
i : integer;
begin
    Result := '[';
     if (VarType(vArray) and VarArray)=0 then
       Result := _VarToStr(vArray)
    else
    for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do
     if i=VarArrayLowBound(vArray, 1)  then
      Result := Result+_VarToStr(vArray[i])
     else
      Result := Result+'|'+_VarToStr(vArray[i]);

    Result:=Result+']';
end;

function VarStrNull(const V:OleVariant):string; //avoid problems with null strings
begin
  Result:='';
  if not VarIsNull(V) then
  begin
    if VarIsArray(V) then
       Result:=VarArrayToStr(V)
    else
    Result:=VarToStr(V);
  end;
end;

function GetWMIObject(const objectName: String): IDispatch; //create the Wmi instance
var
  chEaten: Integer;
  BindCtx: IBindCtx;
  Moniker: IMoniker;
begin
  OleCheck(CreateBindCtx(0, bindCtx));
  OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
  OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
end;

function KeyPressed:boolean; //Detect if an key is pressed
var
NumEvents   : DWORD;
ir          : _INPUT_RECORD;
bufcount    : DWORD;
StdIn       : THandle;
begin
    Result:=false;
    StdIn := GetStdHandle(STD_INPUT_HANDLE);
    NumEvents:=0;
    GetNumberOfConsoleInputEvents(StdIn,NumEvents);
    if NumEvents<> 0 then
    begin
        PeekConsoleInput(StdIn,ir,1,bufcount);
        if bufcount <> 0 then
        begin
            if ir.EventType = KEY_EVENT then
            begin
              if ir.Event.KeyEvent.bKeyDown then
                result:=true
              else
                FlushConsoleInputBuffer(StdIn);
            end
            else
            FlushConsoleInputBuffer(StdIn);
        end;
    end;
end;

Procedure  Event___InstanceCreationEvent_Target_Win32_Process;
var
  objWMIService   : OLEVariant;
  objEvent        : OLEVariant;
  objResult       : OLEVariant;
begin
  objWMIService := GetWMIObject('winmgmts:\\.\root\CIMV2');
  objEvent      := objWMIService.ExecNotificationQuery('Select * from __InstanceCreationEvent Within 1 Where TargetInstance ISA ''Win32_Process''    ');
  while not KeyPressed do
  begin
    try
     objResult := objEvent.NextEvent(100);
    except
     on E:EOleException do
     if EOleException(E).ErrorCode=HRESULT($80043001) then //Check for the timeout error wbemErrTimedOut 0x80043001
       objResult:=Null
     else
     raise;
    end;

    if not VarIsNull(objResult) then
    begin
      Writeln('Caption                  '+VarStrNull(objResult.TargetInstance.Caption));
      Writeln('CommandLine              '+VarStrNull(objResult.TargetInstance.CommandLine));
      Writeln('CreationClassName        '+VarStrNull(objResult.TargetInstance.CreationClassName));
      Writeln('CreationDate             '+VarStrNull(objResult.TargetInstance.CreationDate));
      Writeln('CSCreationClassName      '+VarStrNull(objResult.TargetInstance.CSCreationClassName));
      Writeln('CSName                   '+VarStrNull(objResult.TargetInstance.CSName));
      Writeln('Description              '+VarStrNull(objResult.TargetInstance.Description));
      Writeln('ExecutablePath           '+VarStrNull(objResult.TargetInstance.ExecutablePath));
      Writeln('ExecutionState           '+VarStrNull(objResult.TargetInstance.ExecutionState));
      Writeln('Handle                   '+VarStrNull(objResult.TargetInstance.Handle));
      Writeln('HandleCount              '+VarStrNull(objResult.TargetInstance.HandleCount));
      Writeln('InstallDate              '+VarStrNull(objResult.TargetInstance.InstallDate));
      Writeln('KernelModeTime           '+VarStrNull(objResult.TargetInstance.KernelModeTime));
      Writeln('MaximumWorkingSetSize    '+VarStrNull(objResult.TargetInstance.MaximumWorkingSetSize));
      Writeln('MinimumWorkingSetSize    '+VarStrNull(objResult.TargetInstance.MinimumWorkingSetSize));
      Writeln('Name                     '+VarStrNull(objResult.TargetInstance.Name));
      Writeln('OSCreationClassName      '+VarStrNull(objResult.TargetInstance.OSCreationClassName));
      Writeln('OSName                   '+VarStrNull(objResult.TargetInstance.OSName));
      Writeln('OtherOperationCount      '+VarStrNull(objResult.TargetInstance.OtherOperationCount));
      Writeln('OtherTransferCount       '+VarStrNull(objResult.TargetInstance.OtherTransferCount));
      Writeln('PageFaults               '+VarStrNull(objResult.TargetInstance.PageFaults));
      Writeln('PageFileUsage            '+VarStrNull(objResult.TargetInstance.PageFileUsage));
      Writeln('ParentProcessId          '+VarStrNull(objResult.TargetInstance.ParentProcessId));
      Writeln('PeakPageFileUsage        '+VarStrNull(objResult.TargetInstance.PeakPageFileUsage));
      Writeln('PeakVirtualSize          '+VarStrNull(objResult.TargetInstance.PeakVirtualSize));
      Writeln('PeakWorkingSetSize       '+VarStrNull(objResult.TargetInstance.PeakWorkingSetSize));
      Writeln('Priority                 '+VarStrNull(objResult.TargetInstance.Priority));
      Writeln('PrivatePageCount         '+VarStrNull(objResult.TargetInstance.PrivatePageCount));
      Writeln('ProcessId                '+VarStrNull(objResult.TargetInstance.ProcessId));
      Writeln('QuotaNonPagedPoolUsage   '+VarStrNull(objResult.TargetInstance.QuotaNonPagedPoolUsage));
      Writeln('QuotaPagedPoolUsage      '+VarStrNull(objResult.TargetInstance.QuotaPagedPoolUsage));
      Writeln('QuotaPeakNonPagedPoolUsage'+VarStrNull(objResult.TargetInstance.QuotaPeakNonPagedPoolUsage));
      Writeln('QuotaPeakPagedPoolUsage  '+VarStrNull(objResult.TargetInstance.QuotaPeakPagedPoolUsage));
      Writeln('ReadOperationCount       '+VarStrNull(objResult.TargetInstance.ReadOperationCount));
      Writeln('ReadTransferCount        '+VarStrNull(objResult.TargetInstance.ReadTransferCount));
      Writeln('SessionId                '+VarStrNull(objResult.TargetInstance.SessionId));
      Writeln('Status                   '+VarStrNull(objResult.TargetInstance.Status));
      Writeln('TerminationDate          '+VarStrNull(objResult.TargetInstance.TerminationDate));
      Writeln('ThreadCount              '+VarStrNull(objResult.TargetInstance.ThreadCount));
      Writeln('UserModeTime             '+VarStrNull(objResult.TargetInstance.UserModeTime));
      Writeln('VirtualSize              '+VarStrNull(objResult.TargetInstance.VirtualSize));
      Writeln('WindowsVersion           '+VarStrNull(objResult.TargetInstance.WindowsVersion));
      Writeln('WorkingSetSize           '+VarStrNull(objResult.TargetInstance.WorkingSetSize));
      Writeln('WriteOperationCount      '+VarStrNull(objResult.TargetInstance.WriteOperationCount));
      Writeln('WriteTransferCount       '+VarStrNull(objResult.TargetInstance.WriteTransferCount));
      Writeln('');
    end;
  end;
end;

begin
 try
    CoInitialize(nil);
    try
      Event___InstanceCreationEvent_Target_Win32_Process;
      Readln;
    finally
    CoUninitialize;
    end;
 except
    on E:Exception do
    begin
        Writeln(E.Classname, ':', E.Message);
        Readln;
    end;
  end;
end.

Improved WMi explorer window

this option now shows more info about the wmi classes, including the properties types, methods parameters (in, out)

also includes an option to view the values of the properties of the selected WMI class

and finally a new option called Search WMI Database, this option lets you search in all the wmi classes for a particular word.

see this sample image looking for the Motherboard word

Download The installer from here

And don’t forget , wich all your comments and suggestions are very welcome.

Author: Rodrigo

Just another Delphi guy.

10 thoughts on “WMI Delphi Code Creator – New Features

  1. Hola Rodrigo.
    Veo que sigues mejorando la aplicación. me alegro. Realmente se va a convertir en algo imprescindible para trabajar con WMI y Delphi.

    Como sugerencias, sino te importa te comentaría que:
    * Sigas manteniendo la versión portable (ZIP con el EXE) si es posible. A muchos de nosotros nos sigue gustando instalar (vía instalador) lo menos posible en Windows.
    * Para las Classes (en la pantalla Principal/Code Generation) estaría bien poder disponer de alguna búsqueda rápida; Por ejemplo, para root/CIMV2 hay más de 900 clases y buscarlas en el desplegable es “poco cómodo”.
    * Tal vez utilizaría un poco más los ToolTips.
    * La posible traducción de la aplicación a varios idiomas también sería una mejora considerable. Es posible que en este caso la gente te ayude, sino siempre estará Google. ;-)

    No quiero hacerme tampoco muy pesado. Felicidades de nuevo por ell programa.

    Un saludo.

    • Gracias por tus comentarios Neftali, muchas de las sugerencias que tu mencionas ya lo tengo en mente, para incluirlo en nuevas versiones (esta es solo la segunda version), sobre todo el tema de traducir la aplicacion. a lo mejor los amigos del club delphi nos podrian ayudar con eso ;).

  2. This is very well done. This is the kind add-on that should be built into the Delphi IDE. Thank you for your time and contribution!!

  3. Thank you! Great update in compare to the initial release.

  4. Just one thing; the installer does not as for destination folder, and does not create any icon in Start Menu, so user has to search for the app and find it himself.

  5. Saludos,

    He intentado usar tu generador de código, pero me arroja un error en esta línea al compilar.

    objOutParams := objWMIService.ExecMethod(‘Win32_WindowsProductActivation’, ‘SetProductKey’, objInParams);

    • Hola Maxium, enviame el codigo completo generado por la aplicacion para revisarlo, incluyendo la clase wmi que usaste , el error que te aparece y la version de delphi que usas.

      mi correo es
      rodrigo dot ruz dot v at gmail dot com

  6. Really nice work!
    Comes in handy :-)

Leave a comment