Windows何时发出进程句柄信号?

Chr*_*cke 6 windows winapi synchronization

我有一个自我升级过程,我的主应用程序exe启动一个updater exe在命令行上传递一个句柄.应用程序exe然后调用ExitProcess退出,并且updater在传入的句柄中调用WaitForSingleObject以等待应用程序exe终止.

WaitForSingleObject确实等待.在应用程序调用ExitProcess之前,更新程序会停止.

但是,有时,当更新程序尝试使用新版本覆盖应用程序dll时,我会收到文件锁定错误,当前版本的更新程序将其视为不可恢复的错误并终止.似乎包括任意睡眠(100)足以绕过这个"问题",但我真的很讨厌这样的代码.真的很讨厌.

对我来说,当主应用程序仍处于活动状态以便锁定dll文件时,可以发出进程句柄的信号,这似乎很奇怪.

And*_*sov 2

正如另一个答案指出的那样,当进程停止执行时,进程句柄会收到信号,并且操作系统可能需要更长的时间来释放 DLL。

你是对的,依赖 Sleep(100) 是一个坏主意。您应该将重写 DLL 封装在一个循环中,如下所示:

BOOL UpdateDll(LPCTSTR dll_name, WHATEVER whatever) {
  int tries = 150;
  while (tries--) {
    if (TryUpdateDll(dll_name, whatever))
      return TRUE;
    Sleep(200);
  }
  return FALSE;
}
Run Code Online (Sandbox Code Playgroud)

它会持续尝试卸载 DLL 30 秒,然后放弃。即使系统负载较重,30 秒也应该足够了,但仍然可以防止您的更新程序永远挂起。(如果 UpdateDll 返回 FALSE,请务必向用户提供有意义的错误消息,说明有问题的 DLL 的名称。)

如果您正在搞乱 COM,那么在退出之前调用 CoFreeUnusedLibraries 也可能会有所帮助。( http://msdn.microsoft.com/en-us/library/ms679712.aspx ) 坦率地说,我不知道即使在进程退出后,COM 是否仍会保留 DLL,但最好保持安全。

底线是 Win32 API 中有很多奇怪的地方。只要您能找到可接受的解决方案,您不必处理所有情况。显然 Sleep(100) 可能会中断,但 30 秒的轮询循环对我来说似乎可以接受。