關於dllmain的百度百科的學習。
一個程序要調用dll里的函數,首先要將此dll文件映射到程序進程的地址空間(從磁盤文件映射到內存地址空間 ,PE文件裝載器讀取),要把dll文件映射到程序進程的地址空間有兩種方法:靜態鏈接和動態鏈接的LoadLibrary或者LoadLibraryEx
程序要調用DLL里的函數,使用Loadliabrary時,會調用DLLMain函數。
當一個dll被映射到進程的地址空間時,系統會調用該dll的dllmain 函數,傳遞dwReason參數為DLL_PROCESS_ATTATCH,這種調用只會發生在第一次調用,如果同一進程為后來已經映射進來的dll再次調用LoadLibrary或者LoadLibraryEx,操作系統只會增加dll的調用次數,他不會再用DLL_PROCESS_ATTATCH調用DLL的DLLMAIN。
*****************************************************************
我們知道,在MFC應用程序中CWinApp取代了SDK程序中WinMain的地位,SDK程序WinMain所完成的工作由CWinApp的三個函數完成:
virtual BOOL InitApplication( );
virtual BOOL InitInstance( );
virtual BOOL Run( ); //傳說中MFC程序的“活水源頭”
另外,MFC規則DLL與MFC 應用程序中一樣,需要將所有 DLL中元素的初始化放到InitInstance 成員函數中。
可以試驗一下dllmain的一次調用。增加InitInstance函數,如下:
BOOL CRegularDllApp::InitInstance()
{
// TODO: Add your specialized code here and/or call the base class
CString dxs;
dxs="dxsaslfll";
AfxMessageBox(dxs);
return CWinApp::InitInstance();
}
在應用程序中調用時,如下函數,會首次調用InitInstance函數的AfxMessageBox dxsaslfll,再次點擊按鈕時候不在調用InitInstance.
void CRegularDllCallDlg::OnCalldllButton()
{
typedef void (*lpFun)(void);
HINSTANCE hDll; //DLL句柄
hDll = LoadLibrary("RegularDll.dll");
if (NULL==hDll)
{
MessageBox("DLL加載失敗");
}
//lpFun addFun; //函數指針
lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");//指的是ShowDlg的返回為void 參數為void
if (NULL==pShowDlg)
{
MessageBox("DLL中函數尋找失敗");
}
pShowDlg();
/* AfxMessageBox("dd");*/
}
*****************************************************************
我用一個my.dll,自動聯接av.dll,我用LoadLibrary("my.dll"),GetLastError返回
”指定的模塊找不到“,再用LoadLibraryEx("my.dll",NULL,DONT_RESOLVE_DLL_REFERENCES)就ok.
(附:1. DONT_RESOLVE_DLL_REFERENCES,DONT_RESOLVE_DLL_REFERENCES標志用於告訴系統將DLL映射到調用進程的地址空間中。通常情況下,當DLL被映射到進程的地址空間中時,系統要調用 D L L中的一個特殊函數,即 DllMain。該函數用於對DLL進行初始化。 DONT_RESOLVE_DLL_REFERENCE S標志使系統不必調用Dll Main函數就能映射文件映像。
D L L能夠輸入另一個D L L中包含的函數。當系統將一個 D L L映射到進程的地址空間
中時,它也要查看該DLL是否需要其他的DLL,並且自動加載這些DLL。當DONT_RESOLVE _DLL_REFERENCES標志被設定時,系統並不自動將其他的DLL加載到進程的地址空間中。)
DLL難道是av.dll找不到,但av.dll是我在編譯my.dll時加av.lib自動聯上的,請問有什么直接的辦法來檢測自動聯接的av.dll是否在LoadLibrary("my.dll")時是錯誤之根源??
LoadLibraryEx可設置 DONT_RESOLVE_DLL_REFERENCE使得系統不必調用dllmain函數就能映射dll文件。 DONT_RESOLVE_DLL_REFERENCES:不對DLL進行初始化,僅用於NT。