65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (38投票s)

2006年3月8日

CPOL

2分钟阅读

viewsIcon

460912

downloadIcon

3303

这个库提供了一种简单的方法来读取、修改和保存编译的可执行模块(EXE、DLL、OCX、SCR 等)中的版本信息资源(RT_VERSION)。

引言

这里有几篇关于读取模块版本信息的优秀文章(作者 shaman74Armen Hakobyan),还有一些关于在构建过程中修改 RC 文件(作者 Srinivas Vaithianathangugulea)。

但有时,需要修改已编译的可执行文件或 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 - 主类;从模块读取和写入完整的版本信息资源。包含 CStringFileInfoVS_FIXEDFILEINFOVarFileInfo 结构不是此对象的一部分,因为它基本上是计算得出的数据。在保存修改后的版本信息时,会根据字符串表的数量及其语言-代码页键计算正确的 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 的情况下使用。

© . All rights reserved.