You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Visual C++中如何在程序内部便捷获取自身文件版本号?

当然有更省心的方案!不用费劲找DLL路径再调用GetFileVersionInfo(),这里给你两种实用思路,完美解决你的需求:

方案一:从当前模块资源直接读取版本信息(无需手动获取路径)

这种方法的核心是利用DLL自身的模块句柄直接访问版本资源,完全跳过“定位DLL路径”的步骤:

  1. 确保你的Foo.dll已经包含定义了版本信息的资源文件(.rc),示例如下:
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904B0"
        BEGIN
            VALUE "CompanyName", "Your Company"
            VALUE "FileDescription", "Foo DLL"
            VALUE "FileVersion", "1.0.0.0"
            VALUE "ProductName", "Foo Product"
            VALUE "ProductVersion", "1.0.0.0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END
  1. 在DLL的DllMain中保存自身的模块句柄(这个句柄是系统自动传入的,无需手动获取):
#include <windows.h>

// 全局保存当前DLL的模块句柄
HINSTANCE g_hFooModule = nullptr;

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        g_hFooModule = hModule;
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
  1. 实现GetFooVersion()函数,用模块句柄直接读取版本资源:
#include <vector>
#include <string>

std::wstring GetFooVersion()
{
    if (!g_hFooModule)
        return L"Unknown";

    DWORD dwHandle = 0;
    // 用模块句柄获取版本资源大小,无需文件路径
    DWORD dwSize = GetFileVersionInfoSizeExW(FILE_VER_GET_NEUTRAL, (LPCWSTR)g_hFooModule, &dwHandle);
    if (dwSize == 0)
        return L"Unknown";

    std::vector<BYTE> versionBuffer(dwSize);
    // 读取版本资源
    if (!GetFileVersionInfoExW(FILE_VER_GET_NEUTRAL, (LPCWSTR)g_hFooModule, dwHandle, dwSize, versionBuffer.data()))
        return L"Unknown";

    LPVOID pVersionStr = nullptr;
    UINT strLen = 0;
    // 提取文件版本字符串
    if (VerQueryValueW(versionBuffer.data(), L"\\StringFileInfo\\040904B0\\FileVersion", &pVersionStr, &strLen))
    {
        return std::wstring((LPCWSTR)pVersionStr);
    }

    return L"Unknown";
}

注意:这里用了GetFileVersionInfoSizeExW和GetFileVersionInfoExW,传入模块句柄即可,完全不需要调用GetModuleFileName获取路径

方案二:将版本号编译为常量直接嵌入代码

如果追求极致简单,你可以把版本号定义为宏,在资源文件和代码中共享,这样版本号只需要维护一次,代码里直接返回常量:

  1. 创建一个头文件VersionDefs.h,统一定义版本号:
#define FOO_MAJOR_VERSION 1
#define FOO_MINOR_VERSION 0
#define FOO_BUILD_VERSION 0
#define FOO_REVISION_VERSION 0

#define FOO_VERSION_STRING L"1.0.0.0"
  1. 在资源文件中引用这个头文件,替换硬编码的版本信息:
#include "VersionDefs.h"

VS_VERSION_INFO VERSIONINFO
FILEVERSION FOO_MAJOR_VERSION,FOO_MINOR_VERSION,FOO_BUILD_VERSION,FOO_REVISION_VERSION
PRODUCTVERSION FOO_MAJOR_VERSION,FOO_MINOR_VERSION,FOO_BUILD_VERSION,FOO_REVISION_VERSION
// 其余内容和之前的资源文件一致...
    VALUE "FileVersion", FOO_VERSION_STRING
    VALUE "ProductVersion", FOO_VERSION_STRING
// ...
  1. 实现GetFooVersion(),直接返回常量版本字符串:
#include "VersionDefs.h"
#include <wchar.h>

const wchar_t* GetFooVersion()
{
    return FOO_VERSION_STRING;
}

这种方法完全不需要调用任何Windows API,代码极简,缺点是如果需要自动构建时更新版本号,需要确保头文件的宏定义能被脚本自动修改,但对于大多数场景来说,这是最简便的选择。

总结
  • 如果你需要保证代码返回的版本号和DLL资源中的版本完全一致,且不想手动维护重复信息,方案一更合适;
  • 如果你追求代码最简单、零API调用,方案二是最优解。

内容的提问来源于stack exchange,提问作者Robin Hsu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:39:29