转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家拍砖!
源码下载地址: http://www.rayfile.com/zh-cn/files/bc9d6854-eb7e-11e1-a73e-0015c55db73d/
一、载入dll的另一方法:
1、 导出dll端
(1) 在自己的.cpp文件中定义extern"C"__declspec(dllexport)
这样就得到了导出的接口
(2) 提供给调用者接口.h文件,eg:
#ifndef DELAYLOADLIBAPI #define DELAYLOADLIBAPI extern "C" __declspec(dllimport) #endif /////////////////////////////////////////////////////////////////////////////// DELAYLOADLIBAPI int fnLib(); DELAYLOADLIBAPI intfnLib2();
由于是由宏DELAYLOADLIBAPI 开关,在此.h之前如果没有定义,那么就用dllimport。
2、使用导出dll的模块
(1)#incldue 上面讲到的 接口.h文件
这样会去运行目录下查找DelayLoadLib.dll,如果存在就加载它。
#include "..\20-DelayLoadLib\DelayLoadLib.h" // My DLL function prototypes
(2)判断是否加载此dll。
HMODULE hmod =GetModuleHandle(pszModuleName);
返回值如果不为空,表明已经加载了。
(3)使用接口.
二、 延迟加载
此功能实现了当使用函数时再加载DLL,且可以用API __FUnloadDelayLoadedDLL2主动卸载DLL。
1、添加延迟加载的dll,及链接的lib(实验证明可以不加lib链接)
(1)在目标EXE工程中设置延迟加载的DLL,注意:它的路径是从执行的exe路径开始算的,如果是同一目录,那么直接写名字即可;
如果路径错误,那么会报以下警告:
这是因为VS2008编译器中的确延迟加载DLL模块的使用就是在代码中加入/DELALOAD选项,所以这与我们在代码中直接加入的效果是一样。(出现此警告,表示延迟加载没有实现)
(2)在“附加依赖项”里添加延迟加载的dll对应的lib,它的路径是从exe工程的路径开始算的。
如果不加此lib,编译时报以下 警告:
但不影响执行的情况。
我把链接的lib去掉后,执行时的情况是:
第一步: case dliNotePreLoadLibrary
第二步:
第三步:case dliFailLoadLib
第四步:进入异常处理函数
case VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND):
提示dll没有找到
一开始以前是.lib加载不到引起MSVCR90D.dll加载不到,后来发现是由MSVCR90D.dll没加载到引起的整个执行失败。解决这个问题请参考文章<<>>
2、工程设备里的属性默认是不支持卸载的,为了使卸载DLL的API函数__FUnloadDelayLoadedDLL2有效 ,我们修改工程属性:
3、根据我们绑定的钩子及弹出指明是否加载的Msg框,可以看到执行的过程:
绑定钩子:
// Tell __delayLoadHelper2 to call my hook function PfnDliHook __pfnDliNotifyHook2 = DliHook; PfnDliHook __pfnDliFailureHook2 = DliHook;
// Skeleton DliHook function that does nothing interesting FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli) { FARPROC fp = NULL; // Default return value // NOTE: The members of the DelayLoadInfo structure pointed // to by pdli shows the results of progress made so far. switch (dliNotify) { case dliStartProcessing: // Called when __delayLoadHelper2 attempts to find a DLL/function // Return 0 to have normal behavior or nonzero to override // everything (you will still get dliNoteEndProcessing) break; case dliNotePreLoadLibrary: // Called just before LoadLibrary // Return NULL to have __delayLoadHelper2 call LoadLibary // or you can call LoadLibrary yourself and return the HMODULE fp = (FARPROC) (HMODULE) NULL; break; case dliFailLoadLib: // Called if LoadLibrary fails // Again, you can call LoadLibary yourself here and return an HMODULE // If you return NULL, __delayLoadHelper2 raises the // ERROR_MOD_NOT_FOUND exception fp = (FARPROC) (HMODULE) NULL; break; case dliNotePreGetProcAddress: // Called just before GetProcAddress // Return NULL to have __delayLoadHelper2 call GetProcAddress, // or you can call GetProcAddress yourself and return the address fp = (FARPROC) NULL; break; case dliFailGetProc: // Called if GetProcAddress fails // You can call GetProcAddress yourself here and return an address // If you return NULL, __delayLoadHelper2 raises the // ERROR_PROC_NOT_FOUND exception fp = (FARPROC) NULL; break; case dliNoteEndProcessing: // A simple notification that __delayLoadHelper2 is done // You can examine the members of the DelayLoadInfo structure // pointed to by pdli and raise an exception if you desire break; } return(fp); }
第一步:x = fnLib(); // Attempt to call delay-load function
Case dliNotePreLoadLibrary
第二步: case dliNotePreGetProcAddress
第三步:x =fnLib2();// Attempt to call delay-load function
Case dliNotePreGetProcAddress
第四步:__FUnloadDelayLoadedDLL2(pszDll);
第五步:case dliNotePreLoadLibrary
第六步:case dliNotePreGetProcAddress