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 :
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, WbemScripting_TLB, Vcl.StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private FSink: TSWbemSink; FLocator: ISWbemLocator; FServices: ISWbemServices; procedure EventReceived(ASender: TObject; const objWbemObject: ISWbemObject; const objWbemAsyncContext: ISWbemNamedValueSet); public { Déclarations publiques } end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); const WQL = 'SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Win32_Process"'; begin FLocator := CoSWbemLocator.Create; //Connect to the WMI service FServices := FLocator.ConnectServer('.', 'root\cimv2', '','', '', '', wbemConnectFlagUseMaxWait, nil); //create the sink instance FSink := TSWbemSink.Create(self); //assign the event handler FSink.OnObjectReady := EventReceived; //Run the ExecNotificationQueryAsync FServices.ExecNotificationQueryAsync(FSink.DefaultInterface,WQL,'WQL', 0, nil, nil); end; procedure TForm1.EventReceived(ASender: TObject; const objWbemObject: ISWbemObject; const objWbemAsyncContext: ISWbemNamedValueSet); var PropVal: OLEVariant; begin PropVal := objWbemObject; Memo1.Lines.Add(Format('Caption : %s ',[PropVal.TargetInstance.Caption])); Memo1.Lines.Add(Format('ProcessID : %s ',[PropVal.TargetInstance.ProcessID])); end; end.
Source de ce sode : https://theroadtodelphi.com/2011/04/18/delphi-and-wmi-events/
Dans un premier temps il faut que le paquet LazActiveX
soit installé :
Plus d'infos ici : https://wiki.lazarus.freepascal.org/LazActiveX
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.
WbemScripting_1_2_TLB.pas
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 TSWbemSink
est devenu TEvsSWbemSink
et ses properties ont changé:
TSWbemSink = class(TOleServer) private FOnObjectReady: TSWbemSinkOnObjectReady; FOnCompleted: TSWbemSinkOnCompleted; FOnProgress: TSWbemSinkOnProgress; FOnObjectPut: TSWbemSinkOnObjectPut; FIntf: ISWbemSink; ... function GetDefaultInterface: ISWbemSink; protected procedure InitServerData; override; procedure InvokeEvent(DispID: TDispID; var Params: TVariantArray); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Connect; override; procedure ConnectTo(svrIntf: ISWbemSink); procedure Disconnect; override; procedure Cancel; property DefaultInterface: ISWbemSink read GetDefaultInterface; published property OnObjectReady: TSWbemSinkOnObjectReady read FOnObjectReady write FOnObjectReady; property OnCompleted: TSWbemSinkOnCompleted read FOnCompleted write FOnCompleted; property OnProgress: TSWbemSinkOnProgress read FOnProgress write FOnProgress; property OnObjectPut: TSWbemSinkOnObjectPut read FOnObjectPut write FOnObjectPut; end;
TEvsSWbemSink = Class(TEventSink) Private FOnOnObjectReady:TISWbemSinkEventsOnObjectReady; FOnOnCompleted:TISWbemSinkEventsOnCompleted; FOnOnProgress:TISWbemSinkEventsOnProgress; FOnOnObjectPut:TISWbemSinkEventsOnObjectPut; fServer:ISWbemSink; procedure EventSinkInvoke(Sender: TObject; DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; Params: tagDISPPARAMS; VarResult, ExcepInfo, ArgErr: Pointer); Public constructor Create(TheOwner: TComponent); override; property ComServer:ISWbemSink read fServer; property OnOnObjectReady : TISWbemSinkEventsOnObjectReady read FOnOnObjectReady write FOnOnObjectReady; property OnOnCompleted : TISWbemSinkEventsOnCompleted read FOnOnCompleted write FOnOnCompleted; property OnOnProgress : TISWbemSinkEventsOnProgress read FOnOnProgress write FOnOnProgress; property OnOnObjectPut : TISWbemSinkEventsOnObjectPut read FOnOnObjectPut write FOnOnObjectPut; end;
unit Unit1; {$mode objfpc}{$H+} interface uses ActiveX, StdCtrls, SysUtils, Forms, Controls, Dialogs, WbemScripting_1_2_TLB; type { TForm1 } TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private FSink: TEvsSWbemSink; FLocator: ISWbemLocator; FServices: ISWbemServices; procedure EventReceived(Sender: TObject; objWbemObject: ISWbemObject; objWbemAsyncContext: ISWbemNamedValueSet); public end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); const WQL = 'SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Win32_Process"'; begin FLocator := CoSWbemLocator.Create; //Connect to the WMI service FServices := FLocator.ConnectServer('.', 'root\cimv2', '', '', '', '', wbemConnectFlagUseMaxWait, nil); //create the sink instance FSink := TEvsSWbemSink.Create(self); //assign the event handler FSink.OnOnObjectReady := @EventReceived; //Run the ExecNotificationQueryAsync FServices.ExecNotificationQueryAsync(FSink.ComServer, WQL, 'WQL', 0, nil, nil); end; procedure TForm1.EventReceived(Sender: TObject; objWbemObject: ISWbemObject; objWbemAsyncContext: ISWbemNamedValueSet); var PropVal: olevariant; begin PropVal := objWbemObject; Memo1.Lines.Add(Format('Caption : %s ', [PropVal.TargetInstance.Caption])); Memo1.Lines.Add(Format('ProcessID : %s ', [PropVal.TargetInstance.ProcessID])); end; initialization CoInitializeEx(nil, COINIT_MULTITHREADED); {Je ne sais pas si c'est utile, mais...} finalization; CoUninitialize(); end.