Windows平台可执行文件(exe文件)属性中会有版本信息,包含文件说明、文件版本、版权等信息。但如何通过外部程序修改这些信息呢?当然一些第三方软件已经实现了这些功能,但这不是本文讨论的主题,本文是将设置版本信息的方法公开化。
关于这个问题,我查了msdn,上面只有获取这些信息的api接口,没有设置的接口。下面我们就围绕这个主题分析一下。
简介
Windows下的可执行文件格式属于PE文件格式标准,PE文件标准支持内嵌资源,就是将一个外部文件内嵌到可执行文件中,这样程序启动时只需从自身内部找到这块资源加载就可以了,而不需依赖其他外部的磁盘文件。
当然本文不是讨论如何从PE文件解析获取资源,不过有兴趣可以自己按照PE标准解析内嵌资源。
PE文件支持的内嵌资源都有两个必须的标识:一个是资源类型,一个是资源名称。因此只要知道内嵌资源的这两个标识就能找到对应的资源。**可执行文件的版本信息就是以内嵌资源的方式保存在文件中。**因此若要修改文件的版本信息,只需修改这块资源就行了。
- 资源类型和资源名称可以是数字也可以是字符串。
- 系统已知资源都是以数字来命名的(比如图标资源、版本资源、Manifest资源)。
- 建议自定义资源都用字符串来命名,避免与系统资源冲突。
文件的版本信息以内嵌资源的方式保存在可执行文件中,它的资源类型是RT_VERSION(数字16),资源名称是 MAKEINTRESOURCE(VS_VERSION_INFO)(数字1)。
微软提供了一组通用API接口,用来获取和设置可执行文件的内嵌资源,请看下面详细介绍。
版本数据获取
获取PE文件的版本信息数据有两种获取方法:
1. 通用内嵌资源获取方式。
2. 专用API获取方式。
1. 通用内嵌资源获取方式
通过下面接口可以获取Windows可执行文件中的任何通用资源。
#include <io.h>
#include <string>
std::string GetPEResource(const char* exepath, const char* type,
const char* name, int language = 0)
{
std::string r = "";
if (!exepath)
return r;
//判定文件是否存在
if (_access(exepath, 0) != 0)
return r;
//加载可执行文件
HMODULE hexe = LoadLibrary(exepath);
if (!hexe)
return r;
//查找资源
HRSRC src = FindResourceEx(hexe, type, name, language);
if (src)
{
HGLOBAL glb = LoadResource(hexe, src);
int sz = SizeofResource(hexe, src);
r = std::string((char *)LockResource(glb), sz);
UnlockResource(glb);
FreeResource(glb);
}
//释放可执行文件
FreeLibrary(hexe);
return r;
}
通过对 GetPEResource
接口进行简单调用即可获取PE文件中的版本数据。
std::string rc = GetPEResource( "C:\\测试文件.exe",
RT_VERSION,
MAKEINTRESOURCE(VS_VERSION_INFO),
0);
这样 rc
变量中存储的就是一个完整的、标准的版本信息数据了。
2. 专用API获取方式
微软提供了另外一种专门用于获取文件版本信息的API接口,示例代码如下:
#include <io.h>
#include <string>
std::string GetPEVersionInfo(const char* exepath)
{
std::string r = "";
if (!exepath)
return r;
if (_access(exepath, 0) != 0)
return r;
DWORD sz = GetFileVersionInfoSize(exepath, 0);
r.resize(sz, 0);
return GetFileVersionInfo(exepath, 0, sz, (void*)r.c_str()) ? r : "";
}
通过调用此接口,也可正常获取文件中的版本信息数据。**但此接口返回的缓冲区是自带备份的,并非标准版本数据。**举个例子:假如某exe文件的版本数据大小是N字节,那么调用 GetPEVersionInfo
接口返回的缓冲区大小则是N * 2 + 4字节,前N字节数据为标准的版本数据,中间4字节用 ‘F’ ‘E’ ‘2’ 'X’字符填充,后N个字节用0填充。
版本数据解析
版本数据是格式是一个名叫
VS_VERSIONINFO
的结构体,在msdn上可搜到这个结构体的相关描述。该结构可以认为由三部分构成。
- 第一