This article presents a little tool that we made for maintenance of native console applications, DLLs, device drivers and other non-GUI program components.
Developers often have to add a resource script (.rc) to these components, only because of a version info resource. Text strings in the version resource often need to be changed, and the version number has to be kept in sync. All this is boring and error prone - especially these days, when the version info resources are created automatically for Visual C# apps.
This utility allows adding or modifying the version information whenever needed - in the process of building components, or anytime later. The build process can be simplified, because modules that are common to multiple products, OEM versions and are customized only in the version information, can be built only once.
More to this patching of the version information and some other resource data can be done without access to the code and build environment, so this task can be delayed to the post-build release and packaging steps. For example, marketing or field engineering can easily edit information visible in Windows Explorer and certain resources (such as manifests), without requesting help from developers. This saves time and eliminates possible errors.
The example below modifies file version information of foo.dll in one simple command:
verpatch foo.dll "22.214.171.124 my special build"
A sample scripts included in the source show how to set version information on many files at once, and how to specify all version info elements.
Since the tool is provided in source form, you can easily tweak it to the specific requirements of your products and build procedures.
The code also demonstrates use of Win32 API for native resources and PE image manipulations.
The Version Information resource contains the information visible in the Windows Explorer when you view properties of program files.
As shown on the pictures above, Explorer of WinXP displays all strings in the version info; in newer Windows versions, only few elements are displayed for the same file. However, all the data in the version resource still can be accessed via the Win32 API (
The traditional way of providing this data for native modules is adding a native resource script (.rc file) to the project, adding a
VS_VERSION_INFO resource to the .rc file, compiling it with the Resource Compiler and linking to the binary. This method requires providing all the details of the version info: the file version number, the final name of the file, product name and version, etc. - which may not be known at the build time yet. A .RC file often requires complicated C macros and additional include files.
Anyway, writing version resources by hand is not the best way to spend developer's time, and can be avoided.
The version resource data consists of a "binary" data structure, and array of text string pairs (key and value). In other words, it is kind of a manifest from a pre-.NET, pre-XML era.
Executables produced by some .NET compilers have a version info attribute
AssemblyVersion. This is a 4-part number, like File Version and Product Version, but it is not duplicated in the binary part of the version resource, and can differ from the actual assembly version, as .NET tools see it.
We could not find a formal schema for string attributes data in the version resource, however. Some of the elements are "well known" (such as created by Visual Studio and recognized by Windows Explorer).
One notorious thing about the version info resource is that two string attributes,
ProductVersion, should be text representation of same fields in the binary part. In reality, they may differ, causing confusion.
In Vista and Windows 7, Windows Explorer displays only few of these attributes; others are not visible to end user. The displayed file version number is taken from the binary part of version structure. Comments, Private Build, Special Build attributes, created by Visual Studio are not displayed. If information in these strings should be visible to the end user, consider moving it to elements that remain visible (File description, Product name).
You can modify this tool to automatically reformat version information on your program files, without rebuilding them, so that the version information appears in the best way on the latest Windows OS.
The version info can possibly depend on contents of the file itself, or various manifests attached to the file, or it's debug information (the .pdb file) - but we'll leave this as an exercise for the reader.
Some installers, self-extracting archives and other applications are known to append extra data to executable files. Such data is not a resource, but simply appended to the PE file, for example as by command
copy /b file.exe + data file2.exe.
The program detects such extra data, saves it and appends again after modifying resources. However, the way the data is restored may be not compatible with all these applications. Please, verify that executable files that contain extra data work correctly after modification.
The code to save the extra data (pExtras.c,h) has been contributed by reader Rob from UK, for executables created with BBC Basic (BB4W).
Note that any modification of a PE file breaks its checksum or other integrity envelope, such as digital signature. The tool will automatically fix the checksum (which is required for kernel drivers and protected DLLs), but will not repair signatures. It should be used as the last touch before signing the application files and building packages for deployment.
Using the Code
The code is provided as a Visual C++ 2008 (or Express) project.
We don't provide a precompiled executable, because it can be easily built from the source. You can just compile the utility and run - it is quite useful, even with the limitations mentioned below.
The command line options and usage instructions are described in the readme.txt file with the sources.
The tool "as is" supports two main usage scenarios:
- A file does not have a version resource at all; a new version resource is created.
- A file already has a version resource; only certain parts of it are modified, the rest is preserved.
In the first case, all version info details can be provided as command line arguments, and the missing details will be filled by defaults.
In the second case, the version resource is attached to the binary at build time. Some version info details (file version, special build description) are set later, using this tool.
Since the command line for a complete version info may be too long, it is better to run verpatch from a batch file, or your favorite script language. The script can contain all the version details, or get them from somewhere else, for example, as described here.
rem Example 2: run verpatch to create version info for foodll.dll
set VERSION="126.96.36.199 (%date%)"
set FILEDESCR=/s desc "sample foodll description"
set BUILDINFO=/s pb "Built by %USERNAME%"
set COMPINFO=/s company "sample company" /s (c) "(c) Sample copyleft 2009"
set PRODINFO=/s product "sample product" /pv "188.8.131.52"
verpatch /va foodll.dll %VERSION% %FILEDESCR% %COMPINFO% %PRODINFO% %BUILDINFO%
Of course, using a script, you can update many files at once.
Below is the "classic" RC source of version resource created by verpatch with options above (to produce this output, run verpatch on the sample DLL file again, with switches /vo /xi ). It even can be compiled with RC.
VALUE "FileVersion", "184.108.40.206 (10-Jun-2009)"
VALUE "ProductVersion", "220.127.116.11"
VALUE "OriginalFilename", "foodll.dll"
VALUE "InternalName", "foodll.dll"
VALUE "FileDescription", "sample foodll description"
VALUE "CompanyName", "sample company"
VALUE "LegalCopyright", "(c) Sample copyleft 2009"
VALUE "ProductName", "sample product"
VALUE "PrivateBuild", "Built by username"
VALUE "Translation", 0x0409, 0x04B0
The program is written in very simple C++. It can be compiled with Visual C++ 2005 or 2008 Express, does not depend on MFC, ATL or anything else.
Points of Interest
UpdateResource API allows adding or replacing native resources of a program file, without recompiling or re-linking. This is what we use to accomplish the task. Since the format of
VS_VERSION structure is not likely to change, and is documented in MSDN, we do our own parsing of this structure and do not depend on the Resource compiler.
The program ensures that the file and product version numbers are identical in the binary part of the version structure and in the strings. You only need to specify the numbers once.
Other capabilities, besides of import and export of version resources, that are worth mentioning:
- Adding resource files to executable. This can be useful in many ways: to add or replace XML manifests, or to use application specific raw binary resources. The help text of this program, for example, is such a custom resource, and users can update it using the program itself.
- Use of Win32
imagehlp API to repair the file checksum
- Option to remove the .pdb path from the debug information in the file. We've seen requests from people that consider this path sensitive information and want to remove it. " src="http://www.codeproject.com/script/Forums/Images/smiley_wink.gif" complete="true" />
Compatibility with the Semantic Versioning specification
Some adjustments in this utlity have been made to support the Semantic Versioning (http://semver.org), just because it seems interesting. According to this spec, a version number has three parts (not four) and optional string suffix separated by '-' or '+' character (a space is not a valid separator). Example: 1.2.3-some.thing.1234
Verpatch accepts file and product version in this format, if a new swith /high is specified. Then, the three parts of the version number are interpreted properly, and the version string is preserved in the string part of the version resource (however, users will not see this text in the Windows Explorer, as explained above). If /high not specified, verpatch behaves as before v.1.0.9, for compatibility. Please see the readme file for syntax details.
Limitations of This Version
The most serious limitation is the lack of support for languages in the version parsing and generating code, but this should be easy to fix. I have not done this, because this was not needed for my kind of projects.
Old (non-Unicode) or strange formats of version resources are not handled properly and will probably break the parser.
Please note that cool C++ coding style, strings or memory management are not subjects of this article.
We'd like to port this utility to C# for easier integration for modern .NET build tools, Powershell and so on.
- Rev. 10 (1.0.10): August 2012
- Rev 9 (1.0.9): November 2011
- Rev. 6: Extra data appended to executable file is detected and saved (code provided by a reader)
- Rev. 3: Code fixed to handle LN version resources, .NET executables; article text edited
- Rev. 2: Some improvements in the code, added example scripts, text edited
- The first version of the article and published code: May 2009