Can I get a notification that a process that I did not start is being disabled in Windows XP / 7?

I have a Delphi 6 application that works with the Skype API. I want to know when the Skype client closed, although my software did not start it (so I do not have a process handle). Thus, I can find out if the user can close the Skype client, I can easily get the process ID for the Skype client, there is also a Windows API call or another method that accepts the process ID, where I can get a notification when the process is (Skype client ) completed?

If not, is there a WinApi call that I can use to poll Windows to check if the process ID is still valid or reuse process IDs so that I can get a process ID that belongs to a recently launched process who is not a Skype client, which will invalidate my survey efforts?

+4
source share
3 answers

Call OpenProcess to get the process handle. The right to access SYNCHRONIZE is likely to be sufficient. Then wait on the handle. Sort of:

 HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid); WaitForSingleObject(hProcess, INFINITE); CloseHandle(hProcess); 
+11
source

You can use the __InstanceDeletionEvent internal WMI event to monitor Win32_Process and a filter using the ProcessId property, this event is executed asynchronously in your code.

Check out this code example (written in delphi XE2, but should work in delphi 6 without problems)

Note. Before using it, you need to import the Microsoft WMI Scripting V1.2 library.

 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 information, you can check out this Delphi and WMI Events article.

+6
source

Windows reuses process identifiers, so don't rely on it yourself.

You can use EnumProcesses() to find out which processes are currently running, then capture the file names and process IDs, etc. See this example on MSDN.

+1
source

Source: https://habr.com/ru/post/1394501/


All Articles