Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VisualC++

VC++ Common Versioning

5.00/5 (3 votes)
31 Jul 2013CPOL5 min read 21.7K   131  
This article explains how to implement Common Versioning Mechanism which helps in easy maintenance of product

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:

Sample Image - maximum width is 600 pixels

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.

Image 2

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:

C++
#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

C++
#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:

Image 3


Add the common header file to the beginning of the rc file:

C++
#include "commonver.h"

Go to version section and update it with macros which we have created in Commonver.h.

C++
/////////////////////////////////////////////////////////////////////////////
//
// Version
//

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

C++
#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.

Image 4

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.

C++
#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:
  • Image 5

Step 2: Update the Common header

Add the below code in the CommonVer.h.

C++
#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:

Image 6

Now build the application for 32 bit and the output should be as below:

Image 7

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:
  1. Identify all the components which are part of the product 
  2. Create a Common Version Header file which will maintain the information for all the components
  3. 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.  

License

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