C++外部程序修改exe文件属性信息的版本信息

本文探讨如何通过C++外部程序修改Windows可执行文件(exe)的版本信息,包括介绍PE文件内嵌资源,讲解如何获取和设置资源,以及详细解析和重组版本数据的过程。
摘要由CSDN通过智能技术生成

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上可搜到这个结构体的相关描述。该结构可以认为由三部分构成。

  1. 第一
  • 11
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值