2009-01-22 59 views
6

我有一個自我升級過程實現的地方,我的主應用程序exe啓動一個updater exe在命令行上傳遞一個句柄給自己。應用程序exe然後調用ExitProcess退出,並且更新程序在傳入的句柄上調用WaitForSingleObject以等待應用程序exe終止。Windows何時發出進程句柄信號?

WaitForSingleObject等待。在應用程序調用ExitProcess之前,更新程序確實會停止。

但是,有時,當更新程序試圖用新版本覆蓋應用程序dll時,我得到一個文件鎖定錯誤,其中當前版本的updater將其視爲不可恢復的錯誤並終止。包括任意睡眠(100)似乎足以繞過這個「問題」,但我真的很討厭那樣的代碼。真的很討厭。

對於我來說,似乎很奇怪的是,當主應用程序仍然有足夠的活動時,進程句柄可以發信號通知,以鎖定dll文件。

回答

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退出後繼續保留DLL,但最好是安全的。

底線是在Win32 API中有很多奇怪的東西。只要您能找到可接受的解決方案,您就不必處理所有情況。顯然睡眠(100)可能會中斷,但30秒的輪詢循環似乎可以接受。

2

該過程在應用程序代碼退出時發出信號。操作系統可能需要一點時間才能完全卸載該進程。信號的意思是說「我已經完成了我需要做的事情」,它更有效地釋放其他代碼,可能有真正有用的東西可以做,而不是在操作系統做一些內務時讓代碼等待。

+0

似乎 - 實際上 - 只要有一個有效的退出代碼從GetExitCode()返回,進程句柄就會變成信號。但是,就常見用例而言,最想要等待進程句柄的應用程序是安裝程序/更新程序,需要知道它們何時能夠刪除內容。 – 2009-01-22 08:54:09

0

可能是由於當時某個其他進程鎖定了DLL。測試這種方法的一種方法是在發生這種情況時生成一份報告,說明任何持有DLL的報告。

0

六個月前用一些防病毒軟件看到了這些。嘗試沒有AV,並且至少要確保AV是最新的。

0

如果你們使用的是使用線程,他們可能不會終止(或加入)速度不夠快,如果你不明確地卸載他們 - 如果你曾明確加載它們使用的LoadLibrary

這當然會發生DLL的

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

特別是這一行:

...當 進程終止或調用 FreeLib的DLL被卸載瑞利函數和參考 計數變爲零。如果由於 TerminateProcess或TerminateThread函數而終止進程 ,則系統不會調用DLL入口函數 。

0

爲您解決一個可能的問題......雖然您無法替換使用的dll,但可以重命名它。所以如果你有一個你需要替換的dll,但由於某種原因它正在使用,請將其重命名爲.delete或類似的東西。進行更新,然後讓主程序搜索任何.delete文件,並在啓動時刪除它們。

-don