Visual C++中如何在程序内部便捷获取自身文件版本号?
当然有更省心的方案!不用费劲找DLL路径再调用GetFileVersionInfo(),这里给你两种实用思路,完美解决你的需求:
方案一:从当前模块资源直接读取版本信息(无需手动获取路径)
这种方法的核心是利用DLL自身的模块句柄直接访问版本资源,完全跳过“定位DLL路径”的步骤:
- 确保你的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
- 在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; }
- 实现
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获取路径
方案二:将版本号编译为常量直接嵌入代码
如果追求极致简单,你可以把版本号定义为宏,在资源文件和代码中共享,这样版本号只需要维护一次,代码里直接返回常量:
- 创建一个头文件
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"
- 在资源文件中引用这个头文件,替换硬编码的版本信息:
#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 // ...
- 实现
GetFooVersion(),直接返回常量版本字符串:
#include "VersionDefs.h" #include <wchar.h> const wchar_t* GetFooVersion() { return FOO_VERSION_STRING; }
这种方法完全不需要调用任何Windows API,代码极简,缺点是如果需要自动构建时更新版本号,需要确保头文件的宏定义能被脚本自动修改,但对于大多数场景来说,这是最简便的选择。
总结
- 如果你需要保证代码返回的版本号和DLL资源中的版本完全一致,且不想手动维护重复信息,方案一更合适;
- 如果你追求代码最简单、零API调用,方案二是最优解。
内容的提问来源于stack exchange,提问作者Robin Hsu
相关产品推荐
相关产品推荐

