延迟加载DLL

 

转载请标明是引用于 http://blog.csdn.net/chenyujing1234 

欢迎大家拍砖

 

一、延迟加载DLL:

使用目的:如果在WIN2000中设计的程序使用了WIN98没有的新函数,而要在98上运行,如果不应有延迟加载技术,将会终止进程

方法(两步):

1        常规建立DLL和可执行模块;

2        链接可执行模块时,添加延迟加载开关

a)         /Lib: DelayImp.lib   // 需要DelayImp.lib库(

b)        /DelayLoad: MyDll.dll

///

// 实践:把下面的代码添加给需要此功能的模块

u       #include <delayimp.h>   // 需要的头文件

u       #pragma comment(lib, "Delayimp.lib") // 库

u       #pragma comment(linker, "/DelayLoad:DelayLoadLib.dll") // 延迟加载的库

u       #pragma comment(linker, "/Delay:unload") // 可以手工卸载,可选

u       //#pragma comment(linker, "/Delay:nobind") // 不绑定,通常不要!

///

其他方面:

3       卸载DLL时(如果不自己卸载,则不要这项修改!):

a)         开关:/delayunload  //如果不用此开关,下面的函数将不执行操作!

b)        卸载DLL(不能使用FreeLibrary,否则函数地址不会被清除),使用:

BOOL __FUnloadDelayLoadedDLLPCSTR szDll);//不包含路径

4       延迟加载使.exe文件变大。阻止变大,使用开关:/Delay:nobind(不建议用)。

5.         挂钩函数。接收__delayLoadHelper的进度通知和错误通知,用法(两步):

a)         自己编写挂钩函数(如DliHook);

b)        DelayImp.lib库中俩个PfnDliHook类型的变量__pfnDliNotifyHook, __pfnDliFailureHook。将两个中的一个设置为挂钩函数的地址(PfnDliHook __pfnDliNotifyHook = DliHook

6    细节:

u       程序运行时,对DLL中函数的调用,实际上是对DelayImp.lib库中的__delayLoadHelper函数的调用。__delayLoadHelper引用DLLDelay Import节(调用LoadLibraryGetProcAddres)调用函数。

u       如果有多个DLL需要延迟加载,则要为每一个DLL设定开关。

7         异常处理:

u       如果加载失败,产生一个软件异常(ERROR_MOD_NOT_FOUND, ERROR_PROC_NOT_FOUND),(如果不用SHE处理,进程终止!),其信息包含在DelayLoadInfo结构中,szDllDLL名字,dlp为函数(DelayLoadProc结构),dwLastError—什么原因引发的错误;如果是成功加载,hmodCurDLL加载到的内存地址,pfnCur为函数地址。

 

二、函数转发(在DLL输出节中):

#pragma comment(linker, “/export:SomeFunc=DllWork.SomeOtherFunc”)

你在DLL输出的SomeFunc实际上位于DllWork.dll中的SomeOtherFunc

 

三、DLL转移(Windows98不支持):

用于强制加载程序总是首先查找应用程序的目录。仅需在应用程序的目录中添加一个空文件,文件名必须SuperApp.local。如:可执行文件名为myPrg.exe,添加一个(转移文件)myPrg.exe.local

 

四、改变模块的位置(如果你的程序带有多个DLL模块)

每个可执行模块和DLL模块都有一个首选基地址(分别是:0x004000000x10000000),用于标识模块映射到进程的理想地址空间。如果不能加载到首选基地址,将产生移位节

a)         可以创建不包含移位节的模块。

u       链接开关:/FIXED。可使模块变小,但不能被改变位置,如果不能加载到首选基地址,那么他就根本不能加载,进程异常终止!适用于仅包含资源的DLL

u       链接开关:/SUBSYSTEM:WINDOWS,5.0/SUBSYSTEM:CONSOLE,5.0

b)        如果有多个模块加载到单个地址空间,必须为每个模块设置不同的首选基地址工程设置”->“Link”->“Output”->Base Address=设置的首选基地址(分配粒度64K)。

c)        如果你的程序带有多个DLL模块,有必要改变首选基地址。建议使用实用程序:Rebase.exe(,详见MSDN)。(可以在链接前后执行)。

示例:rebase –b 0x61000000 myDll.dll

u       可以在改变前后,查看基地址:dumpbin /headers myDll.dll。在“OPTIONAL HEADER VALUES”的“image base”项。

五、绑定模块:(实用程序Bind.exe,查看MSDN)。

使程序更快的初始化。在应用程序安装时执行

示例:bind –u myPrg.exe;

u       可以在绑定前后分别查看其输入节:dumpbin /imports myPrg.exe。如果在结尾(Summary)前有“Bound to KERNEL32.dll [……] ……”标识绑定成功!([ ] 内的内容为“时间戳”,其后面接“可读时间戳”)。

u       要把你的DLL模块(系统模块不必要)拷贝到与.exe同一个文件夹

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值