Ceci est une ancienne révision du document !


Conversion WbemScripting_TLB de Delphi vers Lazarus

Énoncé du problème

Dans mes recherches j'ai trouvé du code Delphi faisant (a peu prés) ce que je cherche a faire.

Et effectivement avec Delphi çà marche, mais avec Lazarus, cela ne fonctionne pas !

Le PROBLÈME est ce fichu fichier WbemScripting_TLB.pas qui vient d'une importation d'un fichier TLB C:\WINDOWS\system32\wbem\wbemdisp.TLB pour le fichier originale et C:\Windows\SysWOW64\wbem\wbemdisp.TLB pour le fichier que j'ai moi même régénéré.
Ce fichier n'est pas compatible avec Lazarus.

J'ai donc décidé de créer ce fichier à partir de Lazarus et j'explique ci-dessous comment j'ai fait et les modifications a faire au code source pour que cela fonctionne.

Ci dessous nous allons trouver :

  1. La source originale en Delphi que j'ai trouvé.
  2. Comment importer un TLB avec Lazarus
  3. La source corrigé en Free Pascal

Sources Delphi Originales

Delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7. Vcl.Controls, Vcl.Forms, Vcl.Dialogs, WbemScripting_TLB, Vcl.StdCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Button1: TButton;
  12. Memo1: TMemo;
  13. procedure Button1Click(Sender: TObject);
  14. private
  15. FSink: TSWbemSink;
  16. FLocator: ISWbemLocator;
  17. FServices: ISWbemServices;
  18. procedure EventReceived(ASender: TObject; const objWbemObject: ISWbemObject; const objWbemAsyncContext: ISWbemNamedValueSet);
  19. public
  20. { Déclarations publiques }
  21. end;
  22.  
  23. var
  24. Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.dfm}
  29.  
  30. { TForm1 }
  31.  
  32. procedure TForm1.Button1Click(Sender: TObject);
  33. const
  34. WQL = 'SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Win32_Process"';
  35. begin
  36. FLocator := CoSWbemLocator.Create;
  37. //Connect to the WMI service
  38. FServices := FLocator.ConnectServer('.', 'root\cimv2', '','', '', '', wbemConnectFlagUseMaxWait, nil);
  39. //create the sink instance
  40. FSink := TSWbemSink.Create(self);
  41. //assign the event handler
  42. FSink.OnObjectReady := EventReceived;
  43. //Run the ExecNotificationQueryAsync
  44. FServices.ExecNotificationQueryAsync(FSink.DefaultInterface,WQL,'WQL', 0, nil, nil);
  45. end;
  46.  
  47. procedure TForm1.EventReceived(ASender: TObject;
  48. const objWbemObject: ISWbemObject;
  49. const objWbemAsyncContext: ISWbemNamedValueSet);
  50. var
  51. PropVal: OLEVariant;
  52. begin
  53. PropVal := objWbemObject;
  54. Memo1.Lines.Add(Format('Caption : %s ',[PropVal.TargetInstance.Caption]));
  55. Memo1.Lines.Add(Format('ProcessID : %s ',[PropVal.TargetInstance.ProcessID]));
  56. end;
  57.  
  58. end.

Source de ce sode : https://theroadtodelphi.com/2011/04/18/delphi-and-wmi-events/

Importer un fichier TLB avec Lazarus

LazActiveX

Dans un premier temps il faut que le paquet LazActiveX soit installé :

Plus d'infos ici : https://wiki.lazarus.freepascal.org/LazActiveX

Importer le TLB

Cela nous donne accés a un nouveau menu Importer la bibliothèque de types… :

Une fois cliqué sur le menu on se retrouve dans cette fenêtre.

  • On choisi [ActiveX References]
  • On cherche [Microsoft WMI Scripting]
  • On clique sur OK et cela nous génére un fichier WbemScripting_1_2_TLB.pas

Adaptation du code

ATTENTION il y a de grosses differences entre le code généré en Delphi et celui en Lazarus, hormis le nom du fichier…

Exemple avec TSWbemSink

Exemple TSWbemSink est devenu TEvsSWbemSink et ses properties ont changé:

Delphi
  1. TSWbemSink = class(TOleServer)
  2. private
  3. FOnObjectReady: TSWbemSinkOnObjectReady;
  4. FOnCompleted: TSWbemSinkOnCompleted;
  5. FOnProgress: TSWbemSinkOnProgress;
  6. FOnObjectPut: TSWbemSinkOnObjectPut;
  7. FIntf: ISWbemSink;
  8. ...
  9. function GetDefaultInterface: ISWbemSink;
  10. protected
  11. procedure InitServerData; override;
  12. procedure InvokeEvent(DispID: TDispID; var Params: TVariantArray); override;
  13. public
  14. constructor Create(AOwner: TComponent); override;
  15. destructor Destroy; override;
  16. procedure Connect; override;
  17. procedure ConnectTo(svrIntf: ISWbemSink);
  18. procedure Disconnect; override;
  19. procedure Cancel;
  20. property DefaultInterface: ISWbemSink read GetDefaultInterface;
  21. published
  22. property OnObjectReady: TSWbemSinkOnObjectReady read FOnObjectReady write FOnObjectReady;
  23. property OnCompleted: TSWbemSinkOnCompleted read FOnCompleted write FOnCompleted;
  24. property OnProgress: TSWbemSinkOnProgress read FOnProgress write FOnProgress;
  25. property OnObjectPut: TSWbemSinkOnObjectPut read FOnObjectPut write FOnObjectPut;
  26. end;
Lazarus
  1. TEvsSWbemSink = Class(TEventSink)
  2. Private
  3. FOnOnObjectReady:TISWbemSinkEventsOnObjectReady;
  4. FOnOnCompleted:TISWbemSinkEventsOnCompleted;
  5. FOnOnProgress:TISWbemSinkEventsOnProgress;
  6. FOnOnObjectPut:TISWbemSinkEventsOnObjectPut;
  7.  
  8. fServer:ISWbemSink;
  9. procedure EventSinkInvoke(Sender: TObject; DispID: Integer;
  10. const IID: TGUID; LocaleID: Integer; Flags: Word;
  11. Params: tagDISPPARAMS; VarResult, ExcepInfo, ArgErr: Pointer);
  12. Public
  13. constructor Create(TheOwner: TComponent); override;
  14. property ComServer:ISWbemSink read fServer;
  15. property OnOnObjectReady : TISWbemSinkEventsOnObjectReady read FOnOnObjectReady write FOnOnObjectReady;
  16. property OnOnCompleted : TISWbemSinkEventsOnCompleted read FOnOnCompleted write FOnOnCompleted;
  17. property OnOnProgress : TISWbemSinkEventsOnProgress read FOnOnProgress write FOnOnProgress;
  18. property OnOnObjectPut : TISWbemSinkEventsOnObjectPut read FOnOnObjectPut write FOnOnObjectPut;
  19.  
  20. end;

Code Lazarus

  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8. ActiveX,
  9. StdCtrls,
  10. SysUtils,
  11. Forms,
  12. Controls,
  13. Dialogs,
  14. WbemScripting_1_2_TLB;
  15.  
  16. type
  17.  
  18. { TForm1 }
  19.  
  20. TForm1 = class(TForm)
  21. Button1: TButton;
  22. Memo1: TMemo;
  23. procedure Button1Click(Sender: TObject);
  24. private
  25. FSink: TEvsSWbemSink;
  26. FLocator: ISWbemLocator;
  27. FServices: ISWbemServices;
  28.  
  29. procedure EventReceived(Sender: TObject; objWbemObject: ISWbemObject;
  30. objWbemAsyncContext: ISWbemNamedValueSet);
  31. public
  32.  
  33. end;
  34.  
  35. var
  36. Form1: TForm1;
  37.  
  38. implementation
  39.  
  40. {$R *.lfm}
  41.  
  42. { TForm1 }
  43.  
  44. procedure TForm1.Button1Click(Sender: TObject);
  45. const
  46. WQL = 'SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Win32_Process"';
  47. begin
  48. FLocator := CoSWbemLocator.Create;
  49. //Connect to the WMI service
  50. FServices := FLocator.ConnectServer('.', 'root\cimv2', '', '', '',
  51. '', wbemConnectFlagUseMaxWait, nil);
  52. //create the sink instance
  53. FSink := TEvsSWbemSink.Create(self);
  54. //assign the event handler
  55. FSink.OnOnObjectReady := @EventReceived;
  56. //Run the ExecNotificationQueryAsync
  57. FServices.ExecNotificationQueryAsync(FSink.ComServer, WQL, 'WQL', 0, nil, nil);
  58. end;
  59.  
  60. procedure TForm1.EventReceived(Sender: TObject; objWbemObject: ISWbemObject;
  61. objWbemAsyncContext: ISWbemNamedValueSet);
  62. var
  63. PropVal: olevariant;
  64. begin
  65. PropVal := objWbemObject;
  66. Memo1.Lines.Add(Format('Caption : %s ', [PropVal.TargetInstance.Caption]));
  67. Memo1.Lines.Add(Format('ProcessID : %s ', [PropVal.TargetInstance.ProcessID]));
  68. end;
  69.  
  70. initialization
  71. CoInitializeEx(nil, COINIT_MULTITHREADED); {Je ne sais pas si c'est utile, mais...}
  72.  
  73. finalization;
  74. CoUninitialize();
  75.  
  76. end.

Résultat

Sources & Ressources

Vous pourriez laisser un commentaire si vous étiez connecté.