我是否可以获得有关我未生成的进程在Windows XP/7中关闭的通知?

Rob*_*ler 5 delphi winapi skype process

我有一个与Skype API一起使用的Delphi 6应用程序.我想知道Skype客户端何时关闭,即使我的软件没有启动它(所以我没有它的进程句柄).通过这种方式,我可以知道用户是否关闭Skype客户端我可以非常轻松地获取Skype客户端的进程ID,因此是否有Windows API调用或其他接受进程ID的技术,我可以在进程中获取通知(Skype客户端)已经终止?

如果没有,是否有一个WinApi调用可用于轮询Windows以查看进程ID是否仍然有效,或者Windows是否重用进程ID,因此我有可能最终获得属于最近启动的进程的进程ID那不是Skype客户端,这会使我的投票工作无效吗?

arx*_*arx 12

调用OpenProcess来获取进程句柄.该SYNCHRONIZE访问权可能就足够了.然后等待手柄.就像是:

HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid);
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
Run Code Online (Sandbox Code Playgroud)


RRU*_*RUZ 6

您可以使用__InstanceDeletionEventWMI内部事件来Win32_ProcessProcessId属性监视类和过滤器,此事件在代码中以异步模式运行.

检查此示例代码(以delphi XE2编写,但必须在delphi 6中正常工作而不会出现问题)

注意:您必须先导入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.
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请查看此文章 Delphi and WMI Events