首页 > 系统相关 >20.4 延迟加载DLL--《Windows核心编程》

20.4 延迟加载DLL--《Windows核心编程》

时间:2022-11-23 11:45:25浏览次数:43  
标签:include 20.4 -- MyDll dll DLL 延迟 加载

延迟加载的 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);

 

标签:include,20.4,--,MyDll,dll,DLL,延迟,加载
From: https://www.cnblogs.com/renleiguanchashi/p/16917780.html

相关文章

  • 数值分析 5.X 解线性方程组的直接方法
    矩阵谱分解设\(\boldsymbol{A}=a_{ij}\in\mathbb{R}^{n\timesn}\),若存在数\(\lambda\)(实数或复数)和非零向量\(\boldsymbol{x}=\left(x_{1},x_{2},......
  • AJAX与后端用户交互
    概念ajax能够动态的更新数据,而不刷新页面,这体现了他的异步性,再次能实现在线人数定时查询数据库以下是springboot+ajax更新在线人数<scriptsrc="/webjars/jquery/3.5......
  • 20.5 函数转发器/已知的DLL/DLL重定向/模块的基地址重定位--《Windows核心编程》
    一、函数转发器函数转发器是DLL的输出节(导出段)中的一个项目,用于将对一个函数的调用转至另一个DLL中的另一个函数。可以在DLL中使用函数转发器:#pragmacomment(link......
  • RtspClient简易音视频解码
     可用于rtsp流检测,独立视频解码,音频解码    namespaceRtspClient_Decode{publicpartialclassMainFrom:Form{//视频Disp......
  • 随想录(软件调试)
       对于很多程序员朋友来说,编写代码要比调试代码快乐的多。似乎创造软件比维护软件更能给人带来成就感。然而,在企业里面维护前人留下的代码也是工作中不可缺少的一项内......
  • 嵌入式操作系统内核原理和开发(系统中断仿真)
       在嵌入式操作系统中,最难模仿的是系统中断的问题。在windows下面,这是没有办法的事情。但是在linux下面,却有一个非常便利的条件,那就是linux的信号处理。因为用户程序处......
  • 嵌入式操作系统内核原理和开发(任务创建和堆栈溢出检查)
       虽然写操作系统的博客要比写普通的技术点要麻烦一些,但是心中还是挺开心的。一方面,通过几行代码就可以说明一些问题,把理论实践化,这本身就很具有挑战性;另外一方面还锻......
  • NOIP 2022 游记
    Day-2近日模拟赛状态:打模拟赛:AK了:这么傻逼的模拟赛不是谁都AK,有什么训练效果吗\(\to\)自闭没AK:挂分了:wdnmd怎么又挂分\(\to\)自闭没挂分:wdnmd怎么就......
  • 嵌入式操作系统内核原理和开发(多线程轮转)
       之前我们也谈到了线程创建,基本上简单的系统就可以跑起来了,但是还没有到多线程运行的地步。所以,我们下面试图所要做的工作就是创建更多的线程,让更多的线程运行起来。......
  • 嵌入式操作系统内核原理和开发(通用优先级调度)
       相比较其他调度算法而言,时间片的轮转更多的注重公平性。但是,任务与任务之间也是有先后之分的,有的任务我们希望多安排一些时间片,而有的任务我们则希望少安排一些时间......