Introduction
Maintaining proper product versions is very critical for any product. We do identify our releases based on our product versions.
For example, I have a product by name "Binary Versioning Tool" whose RTM (Released to Market) Version is 2.0.
This creates a benchmark for me to identify the versions which are there in the market for which support needs to be provided.
Whenever a customer reports an issue, identification of issue is also based on version of the product
since an issue with one version might not be there in another one.
Product versioning is also critical for identifying company name and legal copyright of the product, which identifies
the proprietorship of the product.
Apart from this, when we say a product, it comprises several components, so we need to maintain this information
for every component of the product. For some products, it could be 10 components and for some, it could go beyond 100.
So overall, it becomes very critical to maintain the product versioning and doing this needs to be simple and stable.
After going through this article, it should be easy to maintain the product versions.
For VC Projects (i.e Win32/MFC/ATL/COM), we normally update version information in the rc file as shown below:
Whenever there is an update to component version, we do update this in rc file.
Let's take a quick look at the description of various fields used for versioning.
There are is some information which is common to all the components like Product name, company name, Legal copyright.
Adding this information every time for every new component is not a good idea. It should be kept at a common place and then be
used in these rc files.
Consider a scenario in which we plan to revive the product and change the name of the product.
Let's say Product name gets changed from "Network Manager" to "Open Network Manager". In this case, we need to update every single rc file which is part of the product.
This could be painful and chances of error are also high.
It would be really smooth if update needs to be done in only one location.
The same is applicable for company name change for several reasons, one very common being acquisitions.
Common Versioning Procedure
Let's start with a small example in which we have a product by name "Binary Versioning Tool"
and we have 3 components inside the product by name TestApp1
, TestApp2
and TestApp3
.
All 3 components will have their own resource file for versioning which needs to be updated to maintain the complete
version information of the product and individual components.
Let's go through the step by step procedure to achieve the common versioning:
Step 1: Create a Common Header File which will hold the Version information
Let's start creating a common header by the name "CommonVer.h" with the following information:
#define PRODUCT_NAME "Binary Versioning Tool"
#define PRODUCT_VER_VAL 5.0.0.0
#define PRODUCT_VER_STR "5.0.0.0\0"
#define COMPANY_NAME "My Company"
#define LEGAL_COPYRIGHT "Copyright (C) 2013 My Company."
PRODUCT_VER_VAL
and PRODUCT_VER_STR
contains the same information but in different format,
this is how rc file understands the version information.
It would be more clear as we proceed through the example.
Step 2: Add the information for every component to Header File
#define TESTAPP1_VERSION_VAL 1,0,0,0
#define TESTAPP1_VERSION_STR "1.0.0.0\0"
#define TESTAPP1_FILE_DESC "This is Test Application 1"
#define TESTAPP1_FILE_NAME "TestApp1.exe"
#define TESTAPP2_VERSION_VAL 2,0,0,0
#define TESTAPP2_VERSION_STR "2.0.0.0\0"
#define TESTAPP2_FILE_DESC "This is Test Application 2"
#define TESTAPP2_FILE_NAME "TestApp2.exe"
#define TESTAPP3_VERSION_VAL 3,0,0,0
#define TESTAPP3_VERSION_STR "3.0.0.0\0"
#define TESTAPP3_FILE_DESC "This is Test Application 3"
#define TESTAPP3_FILE_NAME "TestApp3.exe"
Step 3: Update the individual rc files for every component
Now open the rc file for TestApp1
as shown below:
Add the common header file to the beginning of the rc file:
#include "commonver.h"
Go to version section and update it with macros which we have created in Commonver.h.
VS_VERSION_INFO VERSIONINFO
FILEVERSION TESTAPP1_VERSION_VAL
PRODUCTVERSION PRODUCT_VER_VAL
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", COMPANY_NAME
VALUE "FileDescription", TESTAPP1_FILE_DESC
VALUE "FileVersion", TESTAPP1_VERSION_STR
VALUE "InternalName", TESTAPP1_FILE_NAME
VALUE "LegalCopyright", LEGAL_COPYRIGHT
VALUE "OriginalFilename", TESTAPP1_FILE_NAME
VALUE "ProductName", PRODUCT_NAME
VALUE "ProductVersion", PRODUCT_VER_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United States) resources
Step 4: Verify the changes
So now, you are ready with CommonVer.h and rc file. Similarly, you can add the changes for other components.
Now everything can be easily controlled from one location i.e., CommonVer.h.
Let's say you want to update the version of the product and component version. Just update the following macros and you are done!!!
#define PRODUCT_VER_VAL 6.0.0.0
#define PRODUCT_VER_STR "6.0.0.0\0"
#define TESTAPP1_VERSION_VAL 2,0,0,0
#define TESTAPP1_VERSION_STR "2.0.0.0\0"
Same changes could be verified by opening rc in GUI. Later, you can build the binary and it would look like this in the Details Tab.
Identifying Applications Architecture
Applications Architecture becomes very important these days, since every product has its 32 and 64 bit versions.
Once the binaries are being built, then they need to be packaged accordingly to ship it for a particular platform.
Many a times, developers or integrators do burn their hands by copying the incorrect architecture binary, for example: Packaging 64 bit binary for a 32 bit system and finally failure is seen during sanity tests or QA or even sometimes Customer issue.
This happens since there is no easier way to identify the binaries architecture by seeing the properties of the binary.
Normally, if I am the developer, I would run a Tool Like "DumpBin" to identify the architecture of the binary, but then this also involves certain efforts. It would be so good if I can get this information somewhere in the binaries properties, i.e., in the Details Tab.
Let's go back to our Common Code, i.e., CommonVer.h.
#define TESTAPP1_FILE_DESC "This is Test Application 1"
In this, we can add the architecture of the binary in the description itself.
But again, this has to be different for 32 and 64 bit versions.
Follow the below steps to achieve this.
Step 1: Add WIN64 Macro
Follow the below steps to add WIN64 Macro:
- Add the Configuration for x64 from Configuration Manager
- Select Configuration as x64
- Add a Macro for 64 bit in preprocessor for rc file as shown below:
Step 2: Update the Common header
Add the below code in the CommonVer.h.
#ifdef WIN64
#define TESTAPP1_FILE_DESC "This is Test Application 1 (64 bit)"
#else
#define TESTAPP1_FILE_DESC "This is Test Application 1 (32 bit)"
#endif
Step 3: Verify the output
Now build the application for 64 bit and the following should be the output:
Now build the application for 32 bit and the output should be as below:
So now it's easy to identify the architecture of the binary by just checking its properties.
Migration of Current Application
Follow these three simple steps to migrate your current products versioning information to a single header file:
- Identify all the components which are part of the product
- Create a Common Version Header file which will maintain the information for all the components
- Update the rc file for all the components with the Macros defined in common header
Limitations
Once the code has been migrated using common versioning mechanism, updating the versions via RC Editor UI, will vanish all the changes done. Changes can be viewed using RC Editor but should not be edited, Versions should be updated only via header file.
History
- 2013-07-27: Initial version.
- 2013-07-31: Updated Limitations.