首页 文章

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

提问于
浏览
6

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

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

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

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

6 回答

  • 2

    正如另一个答案所指出的,当进程停止执行时,进程句柄会发出信号,操作系统可能需要更长的时间来释放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秒的轮询循环似乎对我来说是可以接受的 .

  • 0

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

  • 0

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

  • 0

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

  • 1

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

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

    特别是这一行:

    ...当进程终止或调用FreeLibrary函数并且引用计数变为零时,将卸载DLL . 如果进程因TerminateProcess或TerminateThread函数而终止,则系统不会调用DLL入口点函数 .

  • 0

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

    -don

相关问题