擺脫DLL"地獄"困擾之目前的困境

  在 Windows 系統中,動態庫版本衝突實在是一個老大難的問題了,爲了解決這個問題,除了使用大量現有的工具外,你還可以利用豐富的 Windows APIs 函數構造自己的調試工具和實用程序。作爲例子,本文將提供三個這種類型的工具,討論如何利用它們來解決動態庫的衝突問題。這三個工具分別是:
DllSpy——列出加載到系統中的所有 Dlls 以及所有使用這些 Dlls 的進程;
ProcessSpy——列出系統中所有正在運行的進程以及它們正在使用的 Dlls;
ProcessXP——顯示 Windows XP 所有併發運行的會話(Sessions)清單;
  從所周知,動態庫“地獄”(DLL Hell)已經不是什麼新鮮玩意兒了,如果你使用第三方的 Dlls,肯定會碰到不少與它有關的問題,如找不到入口點,或者庫版本不兼容等。.NET 中允許組件的並行執行,減少了產生這種問題的機率,但是如果你還沒有升級到 .NET 環境,那怎麼辦?針對這種情況,可用的方法是用不同的工具跟蹤 DLL 的依賴性。但是用標準工具跟蹤時,你可能最後得不到所要的信息。許多工具都沒有你需要的功能,比如自動寫日誌文件,跟蹤分析,僅在控制檯操作腳本控制等。

  本文我們先用一些現有的工具來考察系統中的運行進程,然後系統地研究本文提供的三個工具:DllSpy, ProcessSpy 和 ProcessXP,以便在今後的開發或調試中使用這些工具和技術。

  現有的工具

  Depends.exe 是 Visual C++ 自帶的一個工具。它可能是我們經常使用的工具中最簡單的一個工具了,其功能是列出某個應用程序或 DLL 需要的 DLLs。這個程序在本站可以下載(更新版本請到下面這個地址下載:http://www.dependencywalker.com)。如果你需要看某個 DLL 或可執行文件的全路經,可以用它的上下文菜單進行設置:如圖一:


圖一 察看全路經

  對於靜態加載的情況(即應用程序在鏈接過程中將 dlls 對應的 lib 文件鏈接到程序中),這個工具非常好用,但對於版本較新的系統,大多使用 COM 編程接口,或者說是用 COM 對象編程模型,而 COM 對象的實例化都是運行時加載或者說動態加載某個 DLL 文件,然後通過 LoadLibrary 和 GetProcAddress 調用其中某個特殊的函數來實現的。你不知道這個 DLL 是何時、從哪裏被加載的。

  一種確定 DLLs 被動態加載的方法是找出需要被每一個進程加載的 DLL。Sysinternal 公司(http://www.sysinternals.com)提供了一個工具軟件 ListDlls.exe。它是一個控制檯程序,其圖形用戶界面(GUI)版本爲 Process Explorer。如圖二:

圖二 Process Explorer 運行畫面

  除了列出被某個進程使用的 DLLs 之外,還可以用這個工具瞭解某個程序用到了哪個 kernel 對象,從版本3.11之後,Process Explorer 還可以讓你在兩個快照之間輕鬆掃描到新的或未使用的對象。

  有時候在你用 Process Explorer 掃描到某個進程之前,它可能已經被加載然後又在很短的時間內被卸載了。碰到這種情況時,你需要另外一種類型的工具,我們將在後文中討論。

  爲了操縱進程和 DLLs,首先你必須知道每一個被加載的 DLL 被哪些進程使用。本文的例子程序 DllSpy 實現目的即在於此。如圖三所示:

圖三 DllSpy 運行畫面

  DllSpy程序上面的窗格列出的是所有已經加載的 DLL,每選中一個DLL,在下面的窗格中就會列出使用該 DLL 的所有進程。

  而 ProcessSpy 例子程序的功能正好與 DllSpy 相反,它在上面窗格列出系統中所有的運行進程,每選中一個進程,在下面窗格便顯示出此進程使用的所有 DLLs,如圖四所示:

圖四 ProcessSpy 運行畫面

  下面窗格還反映了 DLL 加載的地址是實際地址還是首選地址,以及它們的從屬性是靜態的還是動態的。這些工具的源代碼和可執行程序都可以從本文的下載鏈接中下載,它們也許不完全滿足你的需要,但可以作爲技術參考,對編程工作肯定是有所裨益的。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章