20.4 延迟加载DLL--《Windows核心编程》
延迟加载的 DLL 是个隐含链接的 DLL,它实际上要等到你的代码试图引用 DLL 中包含的一个符号时才进行加载。
DLL延迟加载技术的原理,就是从导入表中去掉某dll这一项,等到正式调用DLL的时候,才会加载DLL文件。
应用场景:
- 应用初始化加载的DLL过多,导致程序初始化时间过长。使用延迟加载,在程序不同阶段分时加载DLL可以解决这个问题。
- 新版本系统的函数,在老版本系统中不存在时,使用延迟加载,在加载dll之前判断系统版本,不存在则不运行新函数。
- 减小编写LoadLibrary, GetProcAddress 而像静态库函数一样直接使用。
请注意,一个导出了字段(如全局变量)的DLL是无法延迟载入的!!!否则链接失败。

给 DLL 设置延迟加载
请注意,/DelayLoad:MyDll.dll这个开关不能用#pragma comment(linker, "/DelayLoad:MyDll.dll")来设置。
给要使用DLL的程序设置:

如果需要自动卸载Dll
给要使用DLL的程序设置:
则需在可选 属性->配置属性->链接器->高级->卸载延迟加载的DLL->是 (/DELAY:UNLOAD);。此时只能调用__FUnloadDelayLoadedDll2(PCSTR szDll)函数,而不能调用FreeLibrary,并且传入的参数不包含路径,且名称与延迟加载的Dll中配置的参数必须保持一致,如果不打算卸载,就可以不指定/DELAY:UNLOAD。

// 卸载需要的头文件
#include <delayimp.h>
#pragma comment(lib, "delayimp")
BOOL TestReturn = __FUnloadDelayLoadedDLL2("Dll1.dll");
测试程序
// exe 程序
#include <iostream>
#include <tchar.h>
#include <Windows.h>
#include <StrSafe.h>
#include "MyDll.h" // dll对应的那个头文件
// 卸载需要的头文件
#include <delayimp.h>
#pragma comment(lib, "delayimp")
// 在项目属性中添加dll对应.lib路径,附加依赖项里添加dll对应的.lib文件名
// 或者 #pragma comment (lib,"D:/Project Files/MyDll/Debug/MyDll.lib")
//延迟加载DLL的名字
TCHAR g_szDelayLoadModuleName[] = TEXT("Dll1");
//延迟加载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, 0);
}
//延迟加载及异常捕获演示:
int main()
{
__try
{
IsModuleLoaded(g_szDelayLoadModuleName); // 还未加载
int sum = Add(2, 43); // 加载MyDll,调用MyDll.dll中导出的API
printf("sum = %d", sum); // 已加载DLL
IsModuleLoaded(g_szDelayLoadModuleName);
BOOL TestReturn = __FUnloadDelayLoadedDLL2("Dll1.dll");
IsModuleLoaded(g_szDelayLoadModuleName); // 已经卸载
}
__except (DelayLoadDllExceptionFilter(GetExceptionInformation()))
{
}
// we can do otherthing ...
}
LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep)
{
return -1;
}
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "MyDll.h"
#include <iostream>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int Add(int a, int b)
{
return a + b;
}
// MyDll.h
#pragma once
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API int Add(int a, int b);
20.4 延迟加载DLL--《Windows核心编程》的更多相关文章
- windows核心编程 DLL技术 【转】
注:本文章转载于网络,源地址为:http://blog.csdn.net/ithzhang/article/details/7051558 本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑 ...
- 《Windows核心编程系列》二十谈谈DLL高级技术
本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑定的技术. 第一种将DLL映射到进程地址空间的方式是直接在源代码中引用DLL中所包含的函数或是变量,DLL在程序运行后由加载程序隐式的载入, ...
- 《windows核心编程系列》十七谈谈dll
DLL全称dynamic linking library.即动态链接库.广泛应用与windows及其他系统中.因此对dll的深刻了解,对计算机软件开发专业人员来说非常重要. windows中所有API ...
- 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。
windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...
- C++Windows核心编程读书笔记
转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...
- 【转】《windows核心编程》读书笔记
这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...
- 【windows核心编程】 第六章 线程基础
Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ① 一个是线程的内核 ...
- 《Windows核心编程》读书笔记 上
[C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...
- 【Windows】windows核心编程整理(下)
windows核心编程整理(上) windows核心编程整理(下) 线程的堆栈 每当创建一个线程时,系统就会为线程的堆栈(每个线程有他自己的堆栈)保留一个堆栈空间区域,并将一些物理存储器提交给这个以保 ...
- 《Windows核心编程系列》十四谈谈默认堆和自定义堆
堆 前面我们说过堆非常适合分配大量的小型数据.使用堆可以让程序员专心解决手头的问题,而不必理会分配粒度和页面边界之类的事情.因此堆是管理链表和数的最佳方式.但是堆进行内存分配和释放时的速度比其他方式都 ...
随机推荐
- vue学习笔记 十六、params方式带参数的页面跳转
系列导航 vue学习笔记 一.环境搭建 vue学习笔记 二.环境搭建+项目创建 vue学习笔记 三.文件和目录结构 vue学习笔记 四.定义组件(组件基本结构) vue学习笔记 五.创建子组件实例 v ...
- 面试重点:webpack
webpack 熟练掌握Webpack的常用配置,能够自己构建前端环境,并进行项目优化; 001.谈谈你对webpack的看法: webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编 ...
- [tslint] Identifier 'loggedIn' is never reassigned; use 'const' instead of 'let'. (prefer-const)
- P1228-递归【黄】
这道大递归我一开始就找对了方向,不过了MLE,然后从网上搜索到了一个贼有用的概念--尾递归,即如果递归的下一句就是return且没有返回值或者返回值不含有递归函数则编译器会做优化,不会压入新的函数而是 ...
- MINGW64 禁用 Bash 路径参数转换
MINGW64 可以让 Windows 无缝使用 Linux 命令,但是路径参数会被转换为 Windows 风格.例如: $ ./adb shell ls /system ls: C:/Program ...
- 如何查找SpringBoot应用中的请求路径(不使用idea)
背景 昨天有个同事向我咨询某个接口的物理表是哪个,由于公司业务较多.这块业务的确不是我负责的,也没有使用idea不能全局搜索(eclipse搜不到jar内的字符串),也就回复了不清楚. 除了自己写代码 ...
- 【scikit-learn基础】--『回归模型评估』之偏差分析
模型评估在统计学和机器学习中具有至关重要,它帮助我们主要目标是量化模型预测新数据的能力. 本篇主要介绍模型评估时,如何利用scikit-learn帮助我们快速进行各种偏差的分析. 1. **R² ** ...
- PG数据库存储验证
PG数据库存储验证 背景 最近学习了SQLServer数据库的varchar和nvarchar的存储 想到PG数据库其实没让选择字符集,也没有nvarchar 所以想学习一下nvarchar的使用情况 ...
- [转帖]goproxy 使用说明
Go 版本要求 建议您使用 Go 1.13 及以上版本, 可以在这里下载最新的 Go 稳定版本. 配置 Goproxy 环境变量 Bash (Linux or macOS) export GOPROX ...
- HanLP — 感知机(Perceptron) -- Python
HanLP - 感知机(Perceptron) 感知机 感知机是根据输入实例的特征向量 x 对其进行二类分类的线性模型: \[f(x)=sign(w\cdot x+b) \] 感知机模型对应于输入空间 ...