【问题标题】:How to check is there a process running with the given handle如何检查是否有使用给定句柄运行的进程
【发布时间】:2015-05-09 15:13:43
【问题描述】:

场景: 从 App1,我需要执行 App2,将 App1.Handle 作为参数传递。 App2 应该等到 App1 关闭。此后,App2 应将 App1.exe 文件替换为更新版本。

  • 有没有更好的方法来更新正在运行的可执行文件?
  • 如果没有.. 在 App2 中,我知道 App1.Handle,我应该检查一下 如果 App1 已关闭。如何验证从 App1.Handle?

编辑:

应用1:

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。
  • @SertacAkyuz:我按照建议做了,效果很好!感谢您的评论!
  • 干得好,诚然我的评论不是很冗长。不客气!

标签: delphi executable handle auto-update


【解决方案1】:

App1.Handle 表示一个窗口句柄。 App2 需要等待 App1 的进程句柄。要获取 App1 的进程句柄,请使用 OpenProcess()GetCurrentProcessId() 作为进程 ID,或使用 DuplicateHandle()GetCurrentProcess() 作为源句柄。然后您可以将句柄传递给 App2,并让 App2 使用WaitForSingleObject() 等待它。当 App1 退出时,将发出句柄信号。然后App2可以关闭句柄并替换App1.exe。

【讨论】:

  • 为什么要使用 OpenProcess(GetCurrentThreadId()) 而不是 DuplicateHandle(GetCurrentProcess()) ,反之亦然? (我的意思是,哪些是差异?)。
  • 只有两种不同的方式来获取 App1 的真实句柄,因为GetCurrentProcess() 返回的伪句柄不适合传递给 App2。但是,DuplicateHandle() 需要 App2 已经在运行,因此欺骗句柄必须通过 IPC 而不是命令行传递给 App2。
  • @DavidHeffernan:我在总结,所以我遗漏了文档中的一些细节。但是,是的,它需要一个进程 ID 而不是线程 ID,所以请改用 GetCurrentProcessId()
  • OpenProcess调用错误,取回的句柄在其他进程中无效,这就是DuplicateHandle存在的原因。我只需传递 PID 并让其他应用程序自己打开一个同步句柄。
  • @Sertac 这不起作用。当第一个进程关闭时,pid 将无效。传递进程句柄是唯一的方法。 OpenProcess 可以返回一个可继承的句柄。
【解决方案2】:

为什么要使用 PID 等待进程终止?为什么不尝试覆盖文件?只要进程仍在运行,就无法覆盖 .EXE 文件。

即。类似:

WHILE NOT CopyFile(NewVersion,InstalledVersion) DO Sleep(100);

当然,您可以加入超时和其他保护措施,但上面向您展示了另一种方法,无需 PID 或其他值来测试...

【讨论】:

  • 对原则点投反对票。当系统提供阻塞机制时,永远不会使用轮询。
  • 但是他要求的解决方案有很多失败的可能性 - f.ex。如果程序的两个实例正在运行,那么他仍然无法覆盖该文件。上述解决方案将测试他真正想要什么——覆盖文件的能力。他真的不在乎程序是否正在运行(该文件也可能被防病毒扫描程序或完全不同的程序打开,因此他仍然无法覆盖,即使只有一个程序实例在运行)。
  • @HeartWare:没关系。如果还有其他正在运行的实例,则跳过更新。
  • @Hwau:但是如果文件在另一个程序中打开怎么办?或者如果它是只读的?或者位于您没有写入权限的网络驱动器上?如果调用您的程序不再运行,那么您仍然无法覆盖文件的可能性要多得多......
  • @HEARTWARE 那又怎样。如果其他东西锁定了文件,那么其他任何东西都不会成功。您的投票也不例外。
猜你喜欢
  • 2013-04-07
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多