Click here to Skip to main content
15,868,349 members
Articles / Desktop Programming / MFC
Article

Modification of Version Information Resources in Compiled Binaries

Rate me:
Please Sign up or sign in to vote.
4.88/5 (37 votes)
2 Nov 2006CPOL2 min read 451.4K   3.3K   68   66
This library provides an easy way to read, modify, and save version information resource(s) (RT_VERSION) in compiled executable modules (EXE, DLL, OCX, SCR etc.).

Introduction

There are several good articles here about reading module version information (by shaman74 and Armen Hakobyan), also there are some about modifying RC files during the build process (by Srinivas Vaithianathan and gugulea).

But sometimes, one needs to modify the version information in a compiled executable(s) or DLL:

  • Change product name, company name, comments, etc. when deploying multiple products under different names (different skins, branding, resources) but same code;
  • Update DLL version numbers without having to modify dozens of RC files;
  • Modify a self-extractable archive's (simple installers) resources to reflect the product name and the version information of the contained application.

Description

This library provides an easy way to read, modify, and save version information resource(s) (RT_VERSION) in compiled executable modules (EXE, DLL, OCX, SCR, etc.).

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();

Classes exported from VerLibInfo

  • CVersionInfo - The main class; reads and writes complete version information resources to/from modules. Contains CStringFileInfo and VS_FIXEDFILEINFO. The VarFileInfo structure is not a part of this object, because it is basically computed data. When saving modified version information, proper VarFileInfo is calculated from the number of string tables and their language-codepage keys.
  • CStringFileInfo - The wrapper for the StringFileInfo structure (contains string tables for different translations of the version information).
  • CStringTable- The wrapper for the string-table structure (contains the actual name-value pairs).
  • CVersionInfoString - The wrapper for the string structure.

CVersionInfo reference

// 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);

Sample usage

The attached file contains a sample project that utilizes the library (VerInfoLibTest). The test tool understands several command line parameters:

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

The code for "-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);
}

The code for "-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);
}

This will produce an output similar to:

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=
------------------------------

The code for updating a given string is very neat (-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();
}

Notes

The code compiles and works in VC6 and 2005 (both MBCS and UNICODE are supported). MFC is used for the container classes, maps etc. The code can be easily ported to be used without MFC.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralGreat...if it worked properly!!!!!! Pin
TwelveNRow9-Jun-20 11:55
TwelveNRow9-Jun-20 11:55 
QuestionChange file Icon Pin
vidur sharam15-Jul-14 22:44
vidur sharam15-Jul-14 22:44 
QuestionFile Version ! help please Pin
wawada8-Aug-13 4:14
wawada8-Aug-13 4:14 
QuestionGood job! Pin
Denis Vasilik21-Mar-12 3:32
Denis Vasilik21-Mar-12 3:32 
GeneralSimple DLL version? Pin
Crusiatus Black10-Jun-11 3:41
Crusiatus Black10-Jun-11 3:41 
GeneralChange Language Pin
-273C15-Mar-11 12:42
-273C15-Mar-11 12:42 
AnswerRe: Change Language Pin
-273C18-Mar-11 3:49
-273C18-Mar-11 3:49 
GeneralSetVersion.exe Pin
Misutka24-May-09 0:19
Misutka24-May-09 0:19 
GeneralAssert failure! [modified] Pin
ehaerim23-Apr-09 10:21
ehaerim23-Apr-09 10:21 
GeneralRe: Assert failure! Pin
Denis Zabavchik23-Apr-09 10:50
Denis Zabavchik23-Apr-09 10:50 
GeneralMissing a 'GetFixedFileVersion' and 'GetFixedProductVersion' Pin
gil_mo1-Dec-08 20:44
gil_mo1-Dec-08 20:44 
News.NET Version Available Pin
dB.30-Jun-08 8:58
dB.30-Jun-08 8:58 
QuestionFile version number limits? Pin
mikeycoltrane10-Jan-08 15:14
mikeycoltrane10-Jan-08 15:14 
GeneralRe: File version number limits? Pin
Denis Zabavchik10-Jan-08 17:01
Denis Zabavchik10-Jan-08 17:01 
AnswerRe: File version number limits? Pin
mikeycoltrane10-Jan-08 17:52
mikeycoltrane10-Jan-08 17:52 
GeneralRe: File version number limits? [modified] Pin
Denis Zabavchik10-Jan-08 18:11
Denis Zabavchik10-Jan-08 18:11 
GeneralRe: File version number limits? Pin
mikeycoltrane10-Jan-08 18:17
mikeycoltrane10-Jan-08 18:17 
GeneralPatching file version (for the sample code) Pin
dB.12-Sep-07 10:10
dB.12-Sep-07 10:10 
GeneralRe: Patching file version (for the sample code) Pin
Denis Zabavchik12-Sep-07 10:20
Denis Zabavchik12-Sep-07 10:20 
GeneralGet Error when rebuild project Pin
ColdSun20-Aug-07 21:16
ColdSun20-Aug-07 21:16 
GeneralInvalid binary produced Pin
Bernd Holz19-Mar-07 7:03
Bernd Holz19-Mar-07 7:03 
Hi,

when I try the sample program to update the file version of my InstallShiled setup.exe the setup.exe no longer works after changing. It looks like there was omething embedded in the binary before which is stripped of when using the VerInfoLib library. The setup.exe was 4011 kB before and 248 kB after the modification.

Any ideas?

Anyway, very useful tool... Smile | :)

Bernd

GeneralRe: Invalid binary produced Pin
Denis Zabavchik19-Mar-07 7:12
Denis Zabavchik19-Mar-07 7:12 
GeneralRe: Invalid binary produced Pin
zandar the great31-Aug-07 9:10
zandar the great31-Aug-07 9:10 
GeneralRe: Invalid binary produced Pin
CharlieMcD3-Oct-07 6:55
CharlieMcD3-Oct-07 6:55 
Questionincorrect fileversion writing Pin
chrislong28-Mar-07 15:21
chrislong28-Mar-07 15:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.