修改已编译二进制文件中的版本信息资源






4.89/5 (38投票s)
这个库提供了一种简单的方法来读取、修改和保存编译的可执行模块(EXE、DLL、OCX、SCR 等)中的版本信息资源(RT_VERSION)。
引言
这里有几篇关于读取模块版本信息的优秀文章(作者 shaman74 和 Armen Hakobyan),还有一些关于在构建过程中修改 RC 文件(作者 Srinivas Vaithianathan 和 gugulea)。
但有时,需要修改已编译的可执行文件或 DLL 的版本信息。
- 在不同名称(不同的皮肤、品牌、资源)下部署多个产品,但使用相同的代码时,更改产品名称、公司名称、注释等;
- 无需修改数十个 RC 文件即可更新 DLL 版本号;
- 修改自解压档案(简单的安装程序)的资源,以反映产品名称和所包含应用程序的版本信息。
描述
这个库提供了一种简单的方法来读取、修改和保存编译的可执行模块(EXE、DLL、OCX、SCR 等)中的版本信息资源(RT_VERSION
)。
CVersionInfo vi(strModulePath); //Initialize version information object, //load first RT_VERSION resource // Set file version in both VS_FIXEDFILEINFO // and in all string tables // FileVersion string will be set // to "4, 5, 0, 3" just like VS does vi.SetFileVersion(4, 5, 0, 3, TRUE /*Update StringTables*/); // Alternatively, if you need to set // non-numeric version number // like 4.5.0.3452Rus.RelB.MFC7 use // vi["FileVersion"] = "4.5.0.3452Rus.RelB.MFC7" // Set Comments string vi["Comments"] = "We will stick to C++"; // Save modified version information to module, // resource id, and language // that we CVersionInfo from vi.Save();
从 VerLibInfo 导出的类
CVersionInfo
- 主类;从模块读取和写入完整的版本信息资源。包含CStringFileInfo
和VS_FIXEDFILEINFO
。VarFileInfo
结构不是此对象的一部分,因为它基本上是计算得出的数据。在保存修改后的版本信息时,会根据字符串表的数量及其语言-代码页键计算正确的VarFileInfo
。CStringFileInfo
-StringFileInfo
结构的包装器(包含不同翻译版本信息的字符串表)。CStringTable
- 字符串表结构的包装器(包含实际的名称-值对)。CVersionInfoString
- 字符串结构的包装器。
CVersionInfo 参考
// Construction/Destruction // Construct uninitialized empty // version information object CVersionInfo(); // Construct object, populate structures // from RT_VERSION resource of a given module CVersionInfo(const CString& strModulePath, LPCTSTR lpszResourceId = NULL /*Auto*/, WORD wLangId = 0xFFFF /*Auto*/); virtual ~CVersionInfo(); //Read version information from module BOOL FromFile(const CString& strModulePath, LPCTSTR lpszResourceId = NULL /*Auto*/, WORD wLangId = 0xFFFF /*Auto*/); //Save version information to module resource //(specify strModulePath, lpszResourceId & wLangId //to copy resource to different module, resource, language) BOOL ToFile(const CString& strModulePath = "", LPCTSTR lpszResourceId = NULL /*Auto*/, WORD wLangId = 0xFFFF /*Auto*/); //Quick save (saves to the same module, resource, //and language that it was loaded from) BOOL Save(); //Resets (removes all string tables //and cleans fixed version info) void Reset(); // Validates object (mostly used to verify //that version information was //successfully loaded from module) BOOL IsValid() const; // Get/Set the order of blocks //(Regular (TRUE) = StringFileInfo first, VarFileInfo 2nd) BOOL GetInfoBlockOrder() const; void SetInfoBlockOrder(BOOL bRegularStringsFirst); // Get reference to CStringFileInfo const CStringFileInfo& GetStringFileInfo() const; CStringFileInfo& GetStringFileInfo(); // Overloaded bracket operators allow //quick access to first string table in StringFileInfo r/w const CString operator [] (const CString &strName) const; CString &operator [] (const CString &strName); // Get reference to VS_FIXEDFILEINFO const VS_FIXEDFILEINFO& GetFixedFileInfo() const; VS_FIXEDFILEINFO& GetFixedFileInfo(); // SetFileVersion - Updates file version //in VS_FIXEDFILEINFO and in string tables //when bUpdateStringTables == TRUE void SetFileVersion(WORD dwFileVersionMSHi, WORD dwFileVersionMSLo, WORD dwFileVersionLSHi, WORD dwFileVersionLSLo, BOOL bUpdateStringTables = TRUE); void SetFileVersion(DWORD dwFileVersionMS, DWORD dwFileVersionLS, BOOL bUpdateStringTables = TRUE); // SetProductVersion - Updates product version // in VS_FIXEDFILEINFO and ALL string tables // when bUpdateStringTables == TRUE void SetProductVersion(WORD dwProductVersionMSHi, WORD dwProductVersionMSLo, WORD dwProductVersionLSHi, WORD dwProductVersionLSLo, BOOL bUpdateStringTables = TRUE); void SetProductVersion(DWORD dwProductVersionMS, DWORD dwProductVersionLS, BOOL bUpdateStringTables = TRUE);
使用示例
附件包含一个利用该库的示例项目(VerInfoLibTest)。测试工具理解几个命令行参数
Test Application for Version Info Library
USAGE:
VerInfoLibTest.exe -system
Prints out version numbers of all DLLs in Windows system folder
VerInfoLibTest.exe -f <FileName>
Prints out version info string tables of a specified module
VerInfoLibTest.exe -u <FileName> <StringName> "<Value>"
Modifies the StringName value in the first String Table
in module version information
EXAMPLES:
VerInfoLibTest.exe -u mydll.dll CompanyName "New company name"
VerInfoLibTest.exe -u mydll.dll Comments "Updated comment"
VerInfoLibTest.exe -f mydll.dll
“-system”的代码
WIN32_FIND_DATA FindFileData; HANDLE hFind; TCHAR szBuf[MAX_PATH]; ::GetSystemDirectory(szBuf, MAX_PATH); CString strSystemFolder = szBuf; hFind = FindFirstFile(strSystemFolder + "\\*.dll", &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { printf ("Invalid File Handle. " "Get Last Error reports %d\n", GetLastError ()); } else { do { CString strModulePath = strSystemFolder + "\\" + FindFileData.cFileName; const CVersionInfo vi(strModulePath); if (vi.IsValid()) { _tprintf(_T("%s\t%s\n"), FindFileData.cFileName, vi["FileVersion"]); } } while (FindNextFile(hFind, &FindFileData)); FindClose(hFind); }
“-f <FileName>”的代码
const CVersionInfo vi(strFilePath); if (vi.IsValid()) { POSITION posTable = vi.GetStringFileInfo().GetFirstStringTablePosition(); while (posTable) { const CStringTable &st = *vi.GetStringFileInfo().GetNextStringTable(posTable); _tprintf(_T("String table %s\n-----") _T("-------------------------\n"), st.GetKey()); POSITION posString = st.GetFirstStringPosition(); while (posString) { const CVersionInfoString &vistr = *st.GetNextString(posString); _tprintf(_T("%s=%s\n"), vistr.GetKey(), vistr.GetValue()); } _tprintf(_T("------------------------------\n")); } } else { _tprintf(_T("Failed to get module version") _T(" information for %s\n"), strFilePath); }
这将产生类似于以下内容的输出
C:\...eProject\Article1\Output\Release>
VerInfoLibTest.exe -f VerInfoLib.dll
String table 040904b0
------------------------------
Comments=
CompanyName=Denis Zabavchik
FileDescription=VerInfoLib DLL
FileVersion=1, 0, 0, 1
InternalName=VerInfoLib
LegalCopyright=Copyright (C) 2006
LegalTrademarks=
OriginalFilename=VerInfoLib.DLL
PrivateBuild=
ProductName=VerInfoLib Dynamic Link Library
ProductVersion=1, 0, 0, 1
SpecialBuild=
------------------------------
更新给定字符串的代码非常简洁(-u <FileName> <StringName> "<Value>")
if (!_tcscmp(argv[1], _T("-u"))) { // 2nd argument is the file path CString strFilePath(argv[2]); CVersionInfo vi(strFilePath); vi[argv[3]] = argv[4]; vi.Save(); }
注释
该代码在 VC6 和 2005 中编译并运行(同时支持 MBCS 和 UNICODE)。MFC 用于容器类、映射等。该代码可以轻松移植为在没有 MFC 的情况下使用。