在 Windows 系統(tǒng)中,動(dòng)態(tài)庫(kù)版本沖突實(shí)在是一個(gè)老大難的問(wèn)題了,為了解決這個(gè)問(wèn)題,除了使用大量現(xiàn)有的工具外,你還可以利用豐富的 Windows APIs 函數(shù)構(gòu)造自己的調(diào)試工具和實(shí)用程序。作為例子,本文將提供三個(gè)這種類型的工具,討論如何利用它們來(lái)解決動(dòng)態(tài)庫(kù)的沖突問(wèn)題。這三個(gè)工具分別是:
DllSpy——列出加載到系統(tǒng)中的所有 Dlls 以及所有使用這些 Dlls 的進(jìn)程;
ProcessSpy——列出系統(tǒng)中所有正在運(yùn)行的進(jìn)程以及它們正在使用的 Dlls;
ProcessXP——顯示 Windows XP 所有并發(fā)運(yùn)行的會(huì)話(Sessions)清單;
從所周知,動(dòng)態(tài)庫(kù)“地獄”(DLL Hell)已經(jīng)不是什么新鮮玩意兒了,如果你使用第三方的 Dlls,肯定會(huì)碰到不少與它有關(guān)的問(wèn)題,如找不到入口點(diǎn),或者庫(kù)版本不兼容等。.NET 中允許組件的并行執(zhí)行,減少了產(chǎn)生這種問(wèn)題的幾率,但是如果你還沒(méi)有升級(jí)到 .NET 環(huán)境,那怎么辦?針對(duì)這種情況,可用的方法是用不同的工具跟蹤 DLL 的依賴性。但是用標(biāo)準(zhǔn)工具跟蹤時(shí),你可能最后得不到所要的信息。許多工具都沒(méi)有你需要的功能,比如自動(dòng)寫日志文件,跟蹤分析,僅在控制臺(tái)操作腳本控制等。
本文我們先用一些現(xiàn)有的工具來(lái)考察系統(tǒng)中的運(yùn)行進(jìn)程,然后系統(tǒng)地研究本文提供的三個(gè)工具:DllSpy, ProcessSpy 和 ProcessXP,以便在今后的開(kāi)發(fā)或調(diào)試中使用這些工具和技術(shù)。
現(xiàn)有的工具
Depends.exe 是 Visual C++ 自帶的一個(gè)工具。它可能是我們經(jīng)常使用的工具中最簡(jiǎn)單的一個(gè)工具了,其功能是列出某個(gè)應(yīng)用程序或 DLL 需要的 DLLs。這個(gè)程序在本站可以下載(更新版本請(qǐng)到下面這個(gè)地址下載:)。如果你需要看某個(gè) DLL 或可執(zhí)行文件的全路經(jīng),可以用它的上下文菜單進(jìn)行設(shè)置:如圖一:
圖一 察看全路經(jīng)
對(duì)于靜態(tài)加載的情況(即應(yīng)用程序在鏈接過(guò)程中將 dlls 對(duì)應(yīng)的 lib 文件鏈接到程序中),這個(gè)工具非常好用,但對(duì)于版本較新的系統(tǒng),大多使用 COM 編程接口,或者說(shuō)是用 COM 對(duì)象編程模型,而 COM 對(duì)象的實(shí)例化都是運(yùn)行時(shí)加載或者說(shuō)動(dòng)態(tài)加載某個(gè) DLL 文件,然后通過(guò) LoadLibrary 和 GetProcAddress 調(diào)用其中某個(gè)特殊的函數(shù)來(lái)實(shí)現(xiàn)的。你不知道這個(gè) DLL 是何時(shí)、從哪里被加載的。
一種確定 DLLs 被動(dòng)態(tài)加載的方法是找出需要被每一個(gè)進(jìn)程加載的 DLL。Sysinternal 公司(http://www.sysinternals.com)提供了一個(gè)工具軟件 ListDlls.exe。它是一個(gè)控制臺(tái)程序,其圖形用戶界面(GUI)版本為 Process Explorer。如圖二:
圖二 Process Explorer 運(yùn)行畫面
除了列出被某個(gè)進(jìn)程使用的 DLLs 之外,還可以用這個(gè)工具了解某個(gè)程序用到了哪個(gè) kernel 對(duì)象,從版本3.11之后,Process Explorer 還可以讓你在兩個(gè)快照之間輕松掃描到新的或未使用的對(duì)象。
有時(shí)候在你用 Process Explorer 掃描到某個(gè)進(jìn)程之前,它可能已經(jīng)被加載然后又在很短的時(shí)間內(nèi)被卸載了。碰到這種情況時(shí),你需要另外一種類型的工具,我們將在后文中討論。
為了操縱進(jìn)程和 DLLs,首先你必須知道每一個(gè)被加載的 DLL 被哪些進(jìn)程使用。本文的例子程序 DllSpy 實(shí)現(xiàn)目的即在于此。如圖三所示:
圖三 DllSpy 運(yùn)行畫面
DllSpy程序上面的窗格列出的是所有已經(jīng)加載的 DLL,每選中一個(gè)DLL,在下面的窗格中就會(huì)列出使用該 DLL 的所有進(jìn)程。
而 ProcessSpy 例子程序的功能正好與 DllSpy 相反,它在上面窗格列出系統(tǒng)中所有的運(yùn)行進(jìn)程,每選中一個(gè)進(jìn)程,在下面窗格便顯示出此進(jìn)程使用的所有 DLLs,如圖四所示:
圖四 ProcessSpy 運(yùn)行畫面
下面窗格還反映了 DLL 加載的地址是實(shí)際地址還是首選地址,以及它們的從屬性是靜態(tài)的還是動(dòng)態(tài)的。這些工具的源代碼和可執(zhí)行程序都可以從本文的下載鏈接中下載,它們也許不完全滿足你的需要,但可以作為技術(shù)參考,對(duì)編程工作肯定是有所裨益的。