Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get notification that a process I did not spawn is shutting down in Windows XP/7?

I have a Delphi 6 application that works with the Skype API. I want to know when the Skype client has shut down even though my software did not launch it (so I don't have a process handle for it). This way I can know if the user shut down the Skype client I can get the process ID for the Skype client fairly easily, so is there a Windows API call or other technique that accepts a process ID where I can get a notification when the process (Skype client) has terminated?

If not, is there a WinApi call that I can use to poll Windows to see if the process ID is still valid, or does Windows reuse process IDs so there's a chance that I could end up with a process ID belonging to a recently launched process that is not the Skype client, which would invalidate my polling efforts?

like image 772
Robert Oschler Avatar asked Feb 02 '12 22:02

Robert Oschler


2 Answers

Call OpenProcess to get a process handle. The SYNCHRONIZE access right will probably be enough. Then wait on the handle. Something like:

HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid);
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
like image 176
arx Avatar answered Sep 30 '22 04:09

arx


You can use the __InstanceDeletionEvent WMI intrinsic event to monitor the Win32_Process class and the filter by the ProcessId property, this event run in async mode in your code.

Check this sample code (Written in delphi XE2, but must work in delphi 6 without problems)

Note : You must import the Microsoft WMI Scripting V1.2 Library before to use it.

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, WbemScripting_TLB;

type
  TWmiAsyncEvent = class
  private
    FWQL      : string;
    FSink     : TSWbemSink;
    FLocator  : ISWbemLocator;
    FServices : ISWbemServices;
    procedure EventReceived(ASender: TObject; const objWbemObject: ISWbemObject; const objWbemAsyncContext: ISWbemNamedValueSet);
  public
    procedure  Start;
    constructor Create(Pid : DWORD);
    Destructor Destroy;override;
  end;

  TFrmDemo = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    AsyncEvent : TWmiAsyncEvent;
  public
    { Public declarations }
  end;

var
  FrmDemo: TFrmDemo;

implementation

{$R *.dfm}

uses
 ActiveX;

{ TWmiAsyncEvent }

constructor TWmiAsyncEvent.Create(Pid: DWORD);
begin
  inherited Create;
  CoInitializeEx(nil, COINIT_MULTITHREADED);
  FLocator  := CoSWbemLocator.Create;
  FServices := FLocator.ConnectServer('.', 'root\CIMV2', '', '', '', '', wbemConnectFlagUseMaxWait, nil);
  FSink     := TSWbemSink.Create(nil);
  FSink.OnObjectReady := EventReceived;
  //construct the WQL sentence with the pid to monitor
  FWQL:=Format('Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA "Win32_Process"  And TargetInstance.ProcessId=%d',[Pid]);

end;

destructor TWmiAsyncEvent.Destroy;
begin
  if FSink<>nil then
    FSink.Cancel;
  FLocator  :=nil;
  FServices :=nil;
  FSink     :=nil;
  CoUninitialize;
  inherited;
end;

procedure TWmiAsyncEvent.EventReceived(ASender: TObject;
  const objWbemObject: ISWbemObject;
  const objWbemAsyncContext: ISWbemNamedValueSet);
var
  PropVal: OLEVariant;
begin      
  PropVal := objWbemObject;
  //do something when the event is received.
  ShowMessage(Format('The Application %s Pid %d was finished',[String(PropVal.TargetInstance.Name), Integer(PropVal.TargetInstance.ProcessId)]));
end;


procedure TWmiAsyncEvent.Start;
begin
 FServices.ExecNotificationQueryAsync(FSink.DefaultInterface,FWQL,'WQL', 0, nil, nil);
end;

procedure TFrmDemo.FormCreate(Sender: TObject);
begin
    //here you must pass the pid of the process
    AsyncEvent:=TWmiAsyncEvent.Create(1852);
    AsyncEvent.Start;
end;

procedure TFrmDemo.FormDestroy(Sender: TObject);
begin
  AsyncEvent.Free;
end;

end.

For more info you can check this article Delphi and WMI Events

like image 31
RRUZ Avatar answered Sep 30 '22 04:09

RRUZ