天天看點

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

一次性進群,長期免費索取教程,沒有付費教程。

教程清單見微信公衆号底部菜單

進微信群回複公衆号:微信群;QQ群:460500587

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

微信公衆号:計算機與網絡安全

ID:Computer-network

DLL(Dynamic Link Library,動态連結庫)是一個可以被其他應用程式調用的程式子產品,其中封裝了可以被調用的資源和函數。動态連結庫的擴充名一般是.DLL,不過有時也可能是其他的。DLL檔案也屬于可執行檔案,隻不過它是依附于EXE檔案來被執行的。一個DLL檔案可以被多個EXE檔案加載。

一、什麼是DLL

Windows作業系統下有非常多的DLL檔案,有的是作業系統的DLL檔案,有的是應用程式的DLL檔案。DLL檔案有什麼好處呢?DLL是動态連結庫,相對應的有靜态連結庫。動态連結庫是在EXE檔案運作時被加載執行的,而靜态連結庫是在OBJ檔案進行連接配接時同時被儲存到程式中。動态連結庫可以減少可執行檔案的體積,在需要的時候進入記憶體等很多好處。

二、編寫一個簡單的DLL程式

我們編寫一個簡單的DLL程式,并在DLL程式中添加一個導出函數。所謂導出函數,就是DLL提供給外部EXE或其他類型的可執行檔案調用的函數,當然DLL本身也可以自己進行調用。我們啟動VC6來編寫一個DLL程式。

啟動VC6程式,單擊菜單“檔案”->“建立”指令,在“Projects”頁籤中的左邊選擇“Win32 Dynamic-Link Library”,在“Project name:”文本框中填寫“FirstDll”,如圖1所示。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

圖1  建立DLL工程

單擊“OK”按鈕,出現“Win32 Dynamic-Link Library– Step 1 of 1”界面,選擇“A simple DLL Project”項,單擊“Finish”按鈕。在然後出現的對話框中直接單擊“OK”按鈕即可。在建立好該工程後,VC6自動生成如下代碼:

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

DLL程式的入口函數是DllMain(),該函數有以下3個參數。

(1)hModule:DLL子產品的句柄。

(2)ul_reason_for_call:DllMain函數被調用的原因。

該參數的取值有4種,分别是DLL_PROCESS_ATTACH(當DLL被某程序加載時DllMain被調用)、DLL_PROCESS_DETACH (當DLL被某程序解除安裝時DllMain被調用)、DLL_THREAD_ATTACH (程序中有線程被建立時DllMain被調用)和DLL_THREAD_DETACH(程序中有線程結束時DllMain被調用)。

(3)lpReserved:保留項,也就是Windows的保留參數。所謂保留參數不是不使用的參數,是Windows不想讓我們知道作用的參數。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

WINAPI也是一個宏,該宏表示一種函數調用約定。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

這樣寫就可以達到根據不同的調用原因執行不同的代碼。我們添加一個簡單的導出函數。

該函數的定義如下:

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

運作函數後彈出一個對話框,顯示一個字元串,并顯示其所在的程序的程序名。我們分别在DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH下加一個對該函數的調用,代碼如下:

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

編譯該代碼,會生成兩個對我們有用的檔案,一個是“FirstDll.dll”,另外一個是“FirstDll.lib”,前面的是DLL檔案,後面的是庫檔案,該庫檔案中包含着導出函數的相關資訊。

三、對DLL程式的調用方法一

DLL程式就寫到這裡,接下來寫個調用該DLL的程式測試一下吧。我們需要對該DLL進行兩方面的測試,一個是看當加載和解除安裝該DLL時,是否會彈出對話框;另外一個是調用這個DLL的導出函數看是否能成功。

在工作區的“Workspace ‘FirstDll’:1project”上單擊右鍵,在彈出的菜單中選擇“Add New Project to Workspace …”,如圖2所示。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

圖2  添加測試工程

彈出“New”對話框,在“Projects”頁籤的左面選擇“Win32 Console Application”,在“Project name:”文本框中填寫:“DllTest1”。單擊“OK”按鈕,在出現的對話框中選擇“A Simple Application”,該處和前面内容類似。在左面的工作區打開我們建立的工程,在DllTest1.cpp中添加代碼:

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

對該代碼進行編譯連接配接,這時并沒有生成我們想要的可執行檔案,在編譯連接配接過程中出錯了。

這個錯誤确切地說是連接配接錯誤,原因是找不到DLL的Lib檔案,我們把“FristDll.lib”檔案複制到DllTest1這個工程的目錄下,再次編譯連接配接,這次通過了。那麼我們就來運作這個DllTest1的程式。不過很可惜,運作出錯,錯誤提示如圖3所示。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

圖3運作DllTest1時的錯誤資訊

這個錯誤的原因是DllTest1找不到FirstDll.dll這個檔案,把開始編譯好的這個檔案也複制到DllTest1的工程目錄下,再次運作,這次一切正常,并且看到彈出3次對話框,說明DLL程式已經能夠正常運作了。

四、對DLL程式的調用方法二

第一種方法是屬于靜态調用,現在的第二種方法屬于動态調用。靜态調用就是在編譯測試程式DllTest1時,FirstDll.dll的資訊就已經寫入了DllTest1的程式中了。對于動态加載的話,就不是編譯時完成了,而是在運作時完成,那麼FirstDll.dll的資訊也不會寫入測試程式中了。現在來寫一個DllTest2程式,該程式的建立方法與DllTest1的建立方法相同。DllTest2的代碼如下:

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

我們對代碼進行編譯連接配接,正常編譯通過。那麼就運作該程式,提示“FirstDll.dll檔案不存在”,這說明DllTest2程式沒有找到FirstDll.dll檔案。把FirstDll.dll檔案拷貝到DllTest2的工程目錄下,再次運作該程式,這次運作成功了,并且應該彈出的3個對話框也都正常彈出了。我們的測試也是成功的。

DLL的動态加載是非常有用的,在DllTest1中,如果無法找到DLL檔案,系統會直接報錯而退出,而在DllTest2中,如果無法找到DLL檔案,程式會給出一個錯誤提示,并且可以繼續運作,而不影響其他代碼的運作。除此而外,如果知道一些API函數,而這些API函數是未文檔化的函數,或者是沒有提供頭檔案的API函數,要怎麼辦呢?比如在前面的内容中用到的函數OpenThread(),該函數在VC6預設的PSDK中是沒有提供定義的,在新的PSDK中才有,那如何使用呢?那就需要用到LoadLibrary()和GetProcAddress()這兩個API函數了。看一下LoadLibrary()和GetProcAddress()這兩個函數的定義:

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

該函數隻有一個參數,就是要加載的DLL檔案的檔案名。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

該函數有兩個參數,hModule是子產品的句柄,lpProcName指定要擷取函數位址的函數名稱。

在關于DLL話題的最後,介紹一下如何檢視DLL程式的導出函數。在這裡介紹兩個工具,一個工具是VC6自帶的工具“Depends”,另一個工具是用來檢視PE結構的工具“PEID”。

首先用“Depends”來檢視DLL的導出函數,如何找到這個工具呢?在VC6的安裝菜單下就可以找到該工具。方法如下:單擊菜單“開始”->“程式”->“Microsoft Visual Studio6.0”->“Microsoft Visual Studio 6.0 Tools”->“Depends”指令,打開該程式,再單擊菜單“File”->“Open…”指令,在“打開”對話框中找到我們寫的FirstDll.dll檔案并打開,如圖4所示。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

圖4  Depends界面

右下角這個區域範圍就是我們的導出函數部分,這裡可以看到導出函數“MsgBox”。

除了這個工具以外,再介紹一個工具——PEID。該工具是用來進行查殼的工具,我們把FirstDll.dll檔案拖曳到PEID界面上,PEID會自動解析出該DLL檔案的PE結構,該界面如圖5所示。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

圖5  PEID界面

可以看到,PEID最下方的編輯框處顯示出DLL是由VC6開發的,而且版本是Debug版本。單擊“子系統”右邊的“

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

”按鈕,會顯示PE結構的詳細資訊,在詳細資訊的下半部分有一個“目錄資訊”,在“目錄資訊”中第一個就是我們想要檢視的導出函數的内容,單擊“導出表”右面的“大于号按鈕

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

”按鈕,出現如圖6所示的界面。

dll load failed: 找不到指定的子產品_Windows 網絡程式設計:DLL程式設計

圖6  導出表資訊

因為DLL中隻有一個導出函數MsgBox(),那麼該導出表中就隻有一個導出項。

對于DLL的程式設計就介紹到這裡了,希望大家可以自己動手完成這個簡單的DLL檔案。

微信公衆号:計算機與網絡安全

ID:Computer-network

【推薦書籍】