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

时间:2009-01-22 08:19:11

标签: windows winapi synchronization

我实现了一个自我升级过程,我的主应用程序exe在命令行上启动一个更新程序exe将句柄传递给自己。应用程序exe然后调用ExitProcess退出,并且updater在传入的句柄中调用WaitForSingleObject以等待应用程序exe终止。

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

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

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

6 个答案:

答案 0 :(得分:2)

当应用程序代码退出时,该过程发出信号。操作系统可能需要更多时间才能完全卸载该过程。信号的意思是说“我已经完成了我需要做的事情”,它更有效地发布其他代码可能有非常有用的东西,而不是让代码等待操作系统做一些内务管理。

答案 1 :(得分:1)

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

你是对的,依赖睡眠(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;
}

这一直试图卸载你的DLL 30秒,然后放弃。即使在系统负载很重的情况下,30秒也应该足够,但仍然可以保护您的更新程序永远不会挂起。 (如果UpdateDll返回FALSE,请务必向用户提供有意义的错误消息,说明有问题的DLL的名称。)

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

底线是Win32 API中有很多奇怪之处。只要您能找到可接受的解决方案,您就不必处理每个案例。显然睡眠(100)可能会中断,但是我可以接受30秒的轮询循环。

答案 2 :(得分:0)

可能是DLL当时被其他进程锁定。测试这种方法的一种方法是生成一个报告,指出在发生这种情况时保留DLL的内容。

答案 3 :(得分:0)

大约六个月前,用一些防病毒软件看到了这些问题。尝试不使用AV,并且至少确保AV是最新的。

答案 4 :(得分:0)

如果您正在使用的任何DLL正在使用线程,如果您没有明确地卸载它们,它们可能不会足够快地终止(或加入) - 如果您使用LoadLibrary明确加载它们,那当然会发生这种情况

看看这里: http://msdn.microsoft.com/en-us/library/ms682596(VS.85).aspx

特别是这一行:

  

...当DLL卸载时   进程终止或调用   FreeLibrary函数和引用   计数变为零。如果是这个过程   由于结束而终止   TerminateProcess或TerminateThread   功能,系统不调用   DLL入口点函数。

答案 5 :(得分:0)

可能的修复方法...虽然您无法替换正在使用的dll,但您可以重命名它。因此,如果您有一个需要替换的DLL,但由于某种原因它正在使用,请将其重命名为.delete或类似的东西。进行更新,然后让主程序搜索任何.delete文件,并在启动时将其删除。

-don