如何检查给定句柄是否正在运行进程

3
场景: 我需要从App1中执行App2并传递App1.Handle作为参数。 App2应该等待App1关闭后再继续执行。在此之后,App2应替换App1.exe文件为已更新的版本。
  • 是否有更好的方法来更新正在运行的可执行文件?
  • 如果没有……在App2中,我知道App1.Handle,我应该如何检查App1是否已经关闭?从App1.Handle开始如何验证?

编辑:

App1:

var
  ProcessHandle : THandle;
begin
  ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, GetCurrentProcessId());
  //Is PROCESS_ALL_ACCESS needed?
  ShellExecute(0, 'open', 'App2.exe', PChar(IntToStr(ProcessHandle)), '.\', SW_SHOW);
end;

应用2:

var
  SenderHandle : THandle;
begin
  if(ParamStr(1) <> '') then
  begin
    SenderHandle := StrToInt(ParamStr(1));
    WaitForSingleObject(SenderHandle, INFINITE);
    ShowMessage('App1 Terminated!');
    //Showmessage is executed when App1 is still running, what's wrong?
  end;
end;

句柄应该是可继承的,请阅读OpenProcess的文档。此外,您应该相应地使用CreateProcess(句柄继承-请参阅文档),而不是ShellExecute。您不需要所有访问权限,同步就足够了。并且您应该检查API的返回值,这样您就会知道您的等待函数是否返回了WAIT_FAILED。 - Sertac Akyuz
@SertacAkyuz:我按照建议做了,现在一切都很好!感谢您的评论! - Hwau
干得好,诚然我的评论不是很详细。不客气! - Sertac Akyuz
2个回答

3
App1.Handle 暗示了一个窗口句柄。而 App2 需要等待 App1 的进程句柄,以此来进行操作。要获取 App1 的进程句柄,可以使用 OpenProcess() 函数,将当前进程 ID 作为参数传入,或者使用 DuplicateHandle() 函数,将当前进程句柄作为源句柄传入。然后将获取到的句柄传递给 App2,在 App2 中使用 WaitForSingleObject() 函数等待该句柄。当 App1 退出时,该句柄将被标记。此时,App2 可以关闭该句柄并替换 App1.exe。

为什么要使用OpenProcess(GetCurrentThreadId())而不是DuplicateHandle(GetCurrentProcess()),或者反之?(我的意思是,它们有什么区别?) - Hwau
@DavidHeffernan:我在总结,所以省略了一些文档中的细节。但是,是需要进程 ID 而不是线程 ID,因此请使用 GetCurrentProcessId() - Remy Lebeau
OpenProcess 的调用是错误的,检索到的句柄在其他进程中将无效,这就是 DuplicateHandle 存在的原因。我只会传递 PID,让其他应用程序自己打开同步句柄。 - Sertac Akyuz
@Sertac,那样是行不通的。当第一个进程关闭时,pid 将无效。传递进程句柄是唯一的方法。OpenProcess 可以返回可继承的句柄。 - David Heffernan
@VitaliyG:是的,但App1会检查是否有其他正在运行的实例。如果有,则跳过更新。 - Hwau
显示剩余4条评论

-1
为什么要等待使用PID终止进程呢?为什么不尝试覆盖文件呢?只要进程还在运行,你就无法覆盖.EXE文件。
比如说:
WHILE NOT CopyFile(NewVersion,InstalledVersion) DO Sleep(100);

当然,你可以加入一个超时和其他保障措施,但上述方法展示了另一种无需使用PID或其他值进行测试的方式...


基于原则的点踩。当系统提供阻塞机制时,永远不应使用轮询。 - David Heffernan
@HeartWare:没关系。如果有其他正在运行的实例,更新将被跳过。 - Hwau
@HeartWare:这是不可能的。 - Hwau
不,那还是错的,或者说最多只是不完整的。你必须先检查CopyFile返回的值。 - David Heffernan
@DavidHeffernan:当文件可能正在使用或由于某些原因被阻止时,您认为CopyFile是最好的方法吗?(我的意思是避免轮询) - Hwau
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接