DLL 延迟加载与资源释放

DLL延迟加载与资源释放延迟加载DLL的延迟加载技术,使用延迟加载方式编译连接可执行文件。这样可执行文件可以先加载执行,而依赖的dll文件会在正式调用的时候被加载进来。好处是可以把必须使用的D

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

DLL 延迟加载与资源释放

延迟加载

DLL的延迟加载技术,使用延迟加载方式编译连接可执行文件。这样可执行文件可以先加载执行,而依赖的dll文件会在正式调用的时候被加载进来。

好处是可以把必须使用的DLL文件以资源方式插入到程序中并且使用延迟加载。在程序运行时把DLL文件释放到本地,然后进行加载。这样exe并不需要依附DLL文件。并且不会担心DLL丢失。

延迟加载实现

延迟加载并不需要代码来实现,只需要对VS链接属性进行设置即可

属性—>链接器—>输入—>延迟加载的DLL—>输入:dll名称

 DLL 延迟加载与资源释放

DLL延迟加载技术的原理,其实就是在导入表中去掉我们想要隐藏的DLL这一项,等到DLL被正式调用的时候,才会加载DLL文件。这样,程序在正式调用DLL之前,都是可以正常执行的。

资源释放

#include <iostream>
#include <iostream>
#include<windows.h>
#include "resource.h"

BOOL FreeMyResource(UINT uiResouceName, char* lpszResourceType, char* lpszSaveFileName);

void GetCurrentPath(char* lpszCurrentPath, DWORD dwSize);

void FreeRes_ShowError(char* pszText);

// CDelayLoadDll_TestDlg 消息处理程序


void FreeRes_ShowError(char* pszText)
{
	char szErr[MAX_PATH] = { 0 };
	::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
	::MessageBox(NULL, szErr, "ERROR", MB_OK);
}

// 释放资源
BOOL FreeMyResource(UINT uiResouceName, char* lpszResourceType, char* lpszSaveFileName)
{
	HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);
	if (NULL == hRsrc)
	{
		FreeRes_ShowError("FindResource");
		return FALSE;
	}
	DWORD dwSize = ::SizeofResource(NULL, hRsrc);
	if (0 >= dwSize)
	{
		FreeRes_ShowError("SizeofResource");
		return FALSE;
	}
	HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
	if (NULL == hGlobal)
	{
		FreeRes_ShowError("LoadResource");
		return FALSE;
	}
	LPVOID lpVoid = ::LockResource(hGlobal);
	if (NULL == lpVoid)
	{
		FreeRes_ShowError("LockResource");
		return FALSE;
	}

	FILE* fp = NULL;
	fopen_s(&fp, lpszSaveFileName, "wb+");
	if (NULL == fp)
	{
		FreeRes_ShowError("LockResource");
		return FALSE;
	}
	fwrite(lpVoid, sizeof(char), dwSize, fp);
	fclose(fp);

	return TRUE;
}


// 获取当前目录
void GetCurrentPath(char* lpszCurrentPath, DWORD dwSize)
{
	::GetModuleFileName(NULL, lpszCurrentPath, dwSize);
	char* p = ::strrchr(lpszCurrentPath, '\\');
	p[0] = '\0';
}

int main()
{
	typedef int (*_pHello)(int a,int b);
	
	// 释放DLL
// 获取当前目录
	char szCurrentPath[MAX_PATH] = { 0 };
	GetCurrentPath(szCurrentPath, MAX_PATH);
	// 构造路径
	::lstrcat(szCurrentPath, "\\hello_world.dll");
	FreeMyResource(IDR_TEST1, "test", szCurrentPath);
	HINSTANCE hDll = LoadLibrary("hello_world.dll");
	_pHello hello = (_pHello)GetProcAddress(hDll, "add");
	int nHello = hello(1,2);
	std::cout << nHello << std::endl;

 DLL 延迟加载与资源释放

查看导入表

 DLL 延迟加载与资源释放

但可以根据PE结构中的资源表IMAGE_RESOURCE_DIRECTORY来解析PE中的所有资源,获取资源的偏移地址和数据大小。

 DLL 延迟加载与资源释放

Tips

  1. 关于如果Visual Studio 2019 出现const char *“ 类型的实参与 “LPCWSTR“ 类型的形参不兼容这类错误。需要修改字符集
  2. 关于如果Visual Studio 2019 出现4996类错误。右击项目文件 — 单击属性 — 配置属性 — c/c++ — 语言 — 符合模式修改符合模式为否。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119851.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 显示搜索dota2协调服务器,搜索dota2游戏协调服务器中【操作方式】

    显示搜索dota2协调服务器,搜索dota2游戏协调服务器中【操作方式】喜欢使用电脑的小伙伴们一般都会遇到win7系统搜索dota2游戏协调服务器中的问题,突然遇到win7系统搜索dota2游戏协调服务器中的问题就不知道该怎么办了,其实win7系统搜索dota2游戏协调服务器中的解决方法非常简单,按照1:DOTA2服务器蹦了之后,进入DOTA2,发现最顶端先是提示:“搜索DOTA2协调服务器中…”2:然后就是显示:“正在连接至DOTA2游戏协调服务器…”来操作就行了,…

    2022年5月17日
    238
  • Java代码 打印九九乘法表

    Java代码 打印九九乘法表Java打印九九乘法表publicclassFor_Demo04{publicstaticvoidmain(String[]args){//打印99乘法表for(intj=1;j<10;j++){for(inti=1;i<10;i++){if(i<=j){

    2022年7月15日
    22
  • continue和break的区别与用法「建议收藏」

    continue和break的区别与用法「建议收藏」一般而言,程序进入循环后在下一次循环测试之间会执行完循环体的所以语句。continue和break语句可以根据循环体中测试结果来忽略一部分循环内容,甚至结束循环。continue语句三种循环都可以使用continue语句。执行到该语句时,会跳过本次迭代(即循环)的剩余部分,并开始下一轮迭代。如果continue语句在嵌套循环内,则只会影响包含该语句的内层循环。语法C语言中continue语句的语法:continue;流程图实例#inclu……

    2025年9月1日
    7
  • MFC常用数据类型

    MFC常用数据类型

    2022年3月12日
    42
  • JAVA程序猿怎么才干高速查找到学习资料?

    JAVA程序猿怎么才干高速查找到学习资料?

    2021年11月30日
    47
  • 记录虚拟机桥接模式不能上网问题的解决方法「建议收藏」

    记录虚拟机桥接模式不能上网问题的解决方法「建议收藏」问题一:一直连接不上网络,右上角的网络模式显示连接不到sudovi/etc/network/interfaces初始情况下,只有以下两行autoloifaceloinetloopback在桥接模式下,需要添加以太网卡的启动,在下面添加两行autoens33ifaceens33inetdhcp看网卡的不同,填不同的,例如eth0,通过ifconfig查看本机网卡问题二:右上角显示连接上了,但是不能ping通外网开启主机的VMwareDHCP.

    2022年4月29日
    494

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号