一、概述:
如果程序额外需要加载一些 DLL 文件、文本文件、图片文件,或者其他的音/视频文件等,则可以把它们作为资源插入到程序里,等到程序运行后,再把它们释放到本地。
这样做的好处是编译出来的程序只有一个 exe 文件,而不需要附带其他文件,因而程序变更很简洁。
二、实现原理:
Windows 操作系统提供了一系列带有操作资源的 WIN32 API 函数。所以,程序实现也是基于这些 WIN32 API 函数进行操作的。
实现步骤:
1、通过 FindResource 定位程序里的资源,主要是根据“资源类型”和“资源名称”进行定位,从而获取资源信息块的句柄。
2、根据上面获取的资源信息块的句柄,利用 SizeofResource 获取资源的大小后,再通过 LoadResource 把资源加载到程序内存中。
3、通过 LockResource 锁定加载到内存中的资源,防止程序中的其他操作影响这块内存。其中,返回值就是资源在进程内存中的起始地址。
4、最后,根据资源大小以及进程内存的起始地址,可将资源数据读取出来并保存为本地文件。
经过上述 4 个步骤,便可以定位出资源,并将其释放到本地硬盘。它的原理就是通过 PE 文件结构,确定资源在 PE 文件中的偏移和大小。
注意:
在资源释放过程中,要特别注意:必须明确资源所在的模块,要指明所在模块句柄并且统一。因为文件可以以资源的形式插入到 DLL 文件中,所以当 DLL 加载到其他进程时,资源所在模块仍是该 DLL 模块。
要想成功释放资源,则需要先通过 GetModualHandle 函数获取该 DLL 模块的句柄。否则,资源释放会因为指定了错误模块而失败。
三、主要代码:
- ResourceFree.h
#ifndef _RESOURCE_FREE_H_
#define _RESOURCE_FREE_H_
#include <windows.h>
BOOL FreeMyResource(UINT uiResouceName, char *lpszResourceType, char *lpszSaveFileName);
BOOL GetResourceInfo(UINT uiResouceName, char *lpszResourceType, PVOID *ppVoid, DWORD *pdwResSize);
BOOL ChangeIcon(char *pszChangedIconExeFileName, char *pszSrcIconExeFileName);