【DLL的隐式加载】: 1.在Lib中包含导入库MyLib.lib 2.cpp中包含头文件MyLib.h 3.运行目录里面包含MyLib.dll 【DLL的显式加载】: 1.运行目录里面包含MyLib.dll 2.LoadLibrary及GetProcAddress 【DLL的延迟加载】: 1.需要DLL,MyLib.lib导入库及MyLib.h 进行【隐式加载】的全步骤 2.属性->配置属性->链接器->输入->延迟加载的Dll-> 添加MyDll.dll(注意/DelayLoad:MyDll.dll这个开关不能用#pragma comment(linker,"/DelayLoad:MyDll.dll")来设置。 3.属性->配置属性->链接器->输入->附加依赖项-> 添加DelayImp.lib //也可以用#include <delayimp.h>和#pragma comment(lib,"Delayimp.lib") //这个开关告诉链接器将delayimp中的__delayLoadHelper2函数嵌入到我们的可执行文件中。 4.如果需要自动卸载Dll,则需在可选 属性->配置属性->链接器->高级->卸载延迟加载的DLL->是 (/DELAY:UNLOAD); //此时只能调用__FUnloadDelayLoadedDll2(PCSTR szDll)函数,而不能调用FreeLibrary //并且传入的参数不包含路径,且名称与延迟加载的Dll中配置的参数必须保持一致,如果不打算卸载,就可以不指定/DELAY:UNLOAD =》好处1.可以在使用多个DLL初始化比较慢的时候,使用这一技术,可以将DLL的载入过程延迟到进程的执行过程中。 =》好处2.当一个函数在老版系统中不存在时,比如GerVersionEx在Windows Vista之前的系统没有此函数,在运行包含了这个函数的老系统中就会出错, =》好处3.减小编写LoadLibrary,GetProcAddress 而像静态库函数一样直接使用. ★延迟加载其实是动态库的隐示加载和显示加载的合并 ★延迟载入是针对隐式链接DLL的 ★一个导出了字段(如全局变量)的DLL是无法延迟载入的 ★Kernel32.dll模块是无法延迟载入的,因为必须载入该模块才能调用LoadLibrary和GetProcAddress。 ★不应在DllMain入口函数中调用一个延迟载入的函数,这可能导致程序崩溃
下面是示例程序:
#include "stdafx.h" #include <windows.h> #include <StrSafe.h> //隐式链接DLL #include "MyDll.h" #pragma comment(lib,"..\\debug\\MyDll.lib") //延迟加载DLL的名字 TCHAR g_szDelayLoadModuleName[] = TEXT("MyDll"); //延迟加载DLL的异常捕获 LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep); //检查是否加载 void IsModuleLoaded(PCTSTR pszModuleName) { HMODULE hmod = GetModuleHandle(pszModuleName); char sz[100] = {0}; StringCchPrintfA(sz,_countof(sz),"MyDll.dll is %S loaded.",(hmod == NULL) ? L"not" : L""); MessageBoxA(NULL,sz,0); } //延迟加载及异常捕获演示: int main() { __try { IsModuleLoaded(g_szDelayLoadModuleName); int sum = fnMyDll(2,43);//调用MyDll.dll中导出的API IsModuleLoaded(g_szDelayLoadModuleName); } __except (DelayLoadDllExceptionFilter(GetExceptionInformation())) { } // we can do otherthing ... } LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep) { return -1; }