![]() |
Platforms, Frameworks & Libraries »
.NET Framework »
Utilities
Intermediate
Automatic Build Versioning in Visual StudioBy Beau SkinnerAutomatic build version awareness, incrementing, and archiving. |
C, C#, VC6, VC7, VC7.1, VC8.0.NET 1.0, .NET 1.1, Win2K, WinXPVS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

Many of your Windows executable files include version information. For example, in the Properties page for my C:\Windows\notepad.exe, the Version tab gives "File version: 5.1.2600.2180" along with other information. In a Visual Studio project, most or all of this information is stored in a resource file (default extension is .rc). I wanted an easy way to add automatic build versioning to my Visual Studio projects that would accomplish the following tasks:
During my initial research I first determined that apparently none of these is natively supported in any version of Visual Studio. I then came across an existing Code Project article about a utility called RCStamp, which parses resource files and modifies the version information within, based on a given format string. This article does not go into the details of RCStamp, so I recommend you read its separate article first.
RCStamp solves task #1 on the list. This article explains the steps I took to solve my other requirements. First I outline the utility applications I created, after which I explain how it all comes together within Visual Studio.
The way I chose to solve the problem of archiving each build was to write a tiny utility application that simply takes a file as input, and copies it to a new file, which is named based on the version information. For example, running VerCopy on my notepad.exe would produce a new file called notepad-5-1-2600.exe. The code only uses the first three numbers of the file version because this is what I wanted. However the source code is extremely simple and is easily modified to suit anybody's needs. Here is the meat of the C# source code:
FileVersionInfo verInfo = FileVersionInfo.GetVersionInfo(PathFile);
string destFile = fileInfo.Name.Substring(0,
fileInfo.Name.Length-fileInfo.Extension.Length) + "-"
+ verInfo.FileMajorPart + "-" + verInfo.FileMinorPart + "-"
+ verInfo.FileBuildPart + fileInfo.Extension;
File.Copy(PathFile, destFile, true);
As you can see, C# makes it a simple matter to access the version information in a given file.
To solve the task of making my projects easily aware of their own current version information, I decided to write another small utility application that parses a resource file and produces a C++ header file with preprocessor constant definitions (#defines): one for major version number, one for minor version number, and a third for build number. Once again, the source code is simple and can quickly be modified to output the version data in any desired format, such as an inclusion file for a different language. Here's what the source looks like:
string line, major, minor, build;
while ((line = RCFile.ReadLine()) != null)
{
int pos;
if ((pos = line.IndexOf("FILEVERSION")) < 0)
continue;
pos += "FILEVERSION".Length + 1;
string[] tempInfo = line.Substring(pos).Split(" .,".ToCharArray());
ArrayList verInfo = new ArrayList(4);
foreach (string s in tempInfo)
if (s.Length > 0)
verInfo.Add(s);
major = verInfo[0].ToString();
minor = verInfo[1].ToString();
build = verInfo[2].ToString();
}
outFile.WriteLine("#define MAJORVERSION {0}", major);
outFile.WriteLine("#define MINORVERSION {0}", minor);
outFile.WriteLine("#define BUILDNUMBER {0}", build);
Here I describe the method I use to add my three build versioning requirements to a Visual Studio project. It is quick and painless and once again the process is easily customizable to suit your needs. The steps I personally use are as follows:
To do this, simply right-click on the project name in Solution Explorer, and select Add->Add Resource... Choose "Version" from the list and click "New". The file will be added to the Resource Files folder for the project and given the same name as the project and the extension ".rc". Double-clicking it will open Resource View. Expanding the Version folder and double-clicking "VS_VERSION_INFO" will show you the contents of the file. Modify it whichever way you like. The "FILEVERSION" field is the one that will be modified by RCStamp and accessed by VerCopy and VerHeader. Be sure to save your changes.
Before we build the application, we want VerHeader to create our header file for us, so we can include it in the application. To do this we add a call to VerHeader in the pre-build event for the project. This is a set of user-defined batch commands that are executed before the build process begins. To access the settings, right-click the project name in Solution Explorer and select Properties... Select "All Configurations" in the Configuration drop-down list and then expand the Build Events folder. In the Command Line field under Pre-Build Event, add:
..\VerHeader "$(ProjectName).rc" version.info
The working directory of the batch commands is the project folder. Usually this is a sub-folder within the solution folder, so VerHeader.exe is contained one step up from the working directory. Visual Studio provides some macros for us to use within these batch commands. $(ProjectName) is self-explanatory. We use it because the resource file's default name is the same as the project name. VerHeader will write to a file called "version.info". You can add a description such as "Updating Version Header..." which will be displayed in Visual Studio's build output window.
Once the application has been built, we want to store a copy of it using VerCopy. In addition, we want to increment the build number in our resource file. So we add calls to VerCopy and RCStamp in the post-build event for the project. This works exactly the same as the pre-build event except that it is called directly after a build succeeds. For the desired configurations, add the following to the post-build command line:
..\VerCopy "$(TargetPath)" "..\Builds\$(ConfigurationName)"
..\RCStamp "$(ProjectName).rc" *.*.+.*
Once again, we use the $(ProjectName) macro to access the resource file. $(TargetPath) is the full path of the output file for the project. $(ConfigurationName) is the name of the configuration that was just built. Therefore VerCopy will copy the output file to a Builds folder within the solution folder, and put it under a sub-folder according to the configuration. Next, RCStamp will increment the third value of the "FILEVERSION" field in the resource file, which I use as the build number. You can add something like "Archiving and Incrementing Build..." in the post-build Description field, which Visual Studio will display in its build output window.
The last step is to include the outputted header file in your application. In C++, simply add a #include "version.info" directive and now you can use the preprocessor constants MAJORVERSION, MINORVERSION, and BUILDNUMBER within the code. This is useful, for example in a console application, for displaying version information to the user, as well as stamping logs with version information.
You will find that these steps are easy to remember, and once you've gone through them, they can be done in a matter of minutes.
I personally find this functionality to be greatly useful in projects with experimental code. I can run performance tests on any builds I wish and release the one with the best results, while working to improve any new changes. Coupled with source control, I finally feel like I have optimal control over not only my code revisions, but also the culmination of sets of revisions into new builds. Hopefully future versions of Visual Studio will provide a full-featured build versioning system, but until that time I feel that my solution is quite adequate. Many thanks to Peter Chen for creating RCStamp, which is really the backbone of this system.
Please contact me with any and all feedback you have regarding this article and the source code. Anything from a spelling correction, to a simplification of the setup process, to a way to improve the source code would be much appreciated. The utilities I wrote are neither highly functional nor highly robust and I would be happy to make any modifications that are important or popularly requested. I would be particularly interested in learning about a scripting method to quickly perform the setup process for a given project within Visual Studio.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 7 May 2005 Editor: Smitha Vijayan |
Copyright 2005 by Beau Skinner Everything else Copyright © CodeProject, 1999-2009 Web18 | Advertise on the Code Project |