Click here to Skip to main content
Click here to Skip to main content

Incrementing AssemblyVersion revision number on each build

By , 2 Oct 2011
 

On each release (or build operation), we are incrementing our build number to flag that we've done something different. Although Visual Studio has an auto-build/revision feature (use the "*" in the AssemblyVersion attribute), like the following code shows:

[assembly: AssemblyVersion("1.0.0.*")]

However, that number begins from a very large value. Some of us would love to start from 1 and increment the revision number one by one. Hereby, I wrote this script to do the job.

var al = WScript.Arguments.length;
if (al < 1) {
    WScript.StdErr.WriteLine ("Error: Missing input file name.");
    WScript.Quit(-1);
}
var n = WScript.Arguments(0); // file name
var c = al > 1 ? WScript.Arguments(1) : ""; // config name

var sh = new ActiveXObject("Shell.Application");
var f = sh.NameSpace(n.replace(/\\[^\\]+$/g, "")).ParseName(n.replace(/.+?\\([^\\]+)$/g, "$1"));
var ft = f.ModifyDate; // Keep the original modification date/time of the file

var s = new ActiveXObject("ADODB.Stream");
    s.Open();
    s.Type = 2;
    s.CharSet = "UTF-8"; // Make SURE that the encoding is correct, otherwise damage may occur
    s.LoadFromFile (n);
var t = s.ReadText ();
var r = /\[assembly:\s*(System\.Reflection\.)?AssemblyVersion(
               ?:Attribute)?\s*\(\s*"(\d+\.\d+\.)(\d+)\.(\d+)"\s*\)\s*\]/g;
var a = r.exec(t);
if (a != null && a.length > 1) {
    var ns = a[1]; // System.Reflection.
    var m = a[2]; // Major.Minor.
    var b = parseInt(a[3]); // Build
    var rv = parseInt(a[4]); // Revision
    if (c != "Release") { // change the number according to the build configuration
        rv++;
    }
    else {
        b++;
    }
    var v = "[assembly: "+ns+"AssemblyVersion (\""+m+b+"."+rv+"\")]";
    WScript.StdOut.WriteLine ("Assembly version changed: " + a[0] + "->" + v);
    t = t.replace(r, v);
}
else {
    WScript.StdErr.WriteLine ("Error: AssemblyVersion not found.");
    WScript.Quit(-1);
}

// further processing of the file is possible here

// save the result
s.Position = 0;
s.WriteText (t);
s.SetEOS ();
s.SaveToFile (n, 2);
s.Close ();

f.ModifyDate = ft; // Reset the modification date/time to prevent unnecessary rebuild afterwards

The above code simply reads a C# file, searches the "[assembly: AssemblyVersion" part of it and uses a regular expression to replace the revision number.

Having the above code, we can save it as a JavaScript file (I save the file into the solution directory and name it as "AutoIncrementBuildNumber.js") and add the following line onto the post-build procedure of the project. Therefore, the build/revision number will automatically be increased by one after each successful release or rebuild.

CScript.exe "$(SolutionDir)AutoIncrementBuildNumber.js" 
  "$(SolutionDir)Properties\AssemblyInfo.cs" "$(ConfigurationName)"

The build number will be incremented after each release. The revision number will be incremented on each debug build. If you don't provide the "$(ConfigurationName)" argument on the above line of post-build event, only revision number will be changed.

If you don't want to increment the build/revision number when you are debugging, you can use conditional statements to limit the increment to "Release" builds only, like the following command shows:

if /I "$(ConfigurationName)" == "Release" CScript.exe "$(SolutionDir)AutoIncrementBuildNumber.js" 
   "$(SolutionDir)Properties\AssemblyInfo.cs"

Rewriting the AssemblyInfo.cs file will change its modification time and cause the compiler to rebuild the project each time you build the solution in Visual Studio, even if you don't change any code files in that project, since the AssemblyInfo.cs file is modified after a successful build and has a later modification time than the target assembly file. This can cause some problems. To avoid such kind of unnecessary rebuilds, the code first retrieves the modification time of the AssemblyInfo.cs file and then reset it after incrementing the build number. Therefore, the modification time is unchanged and Visual Studio won't rebuild the project unless you do make some modification to the source code files. The following is the code which does the job of avoiding rebuild:

var sh = new ActiveXObject("Shell.Application");
var f = sh.NameSpace(n.replace(/\\[^\\]+$/g, "")).ParseName(n.replace(/.+?\\([^\\]+)$/g, "$1"));
var ft = f.ModifyDate; // Keep the original modification date/time of the file
...
f.ModifyDate = ft; // Reset the modification date/time to prevent unnecessary rebuild

Hope this helps.

License

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

About the Author

wmjordan
China China
Member
Chinese Poetry Lover.
Programmer.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralReason for my vote of 4 goodmemberJai Mallesh10 Oct '11 - 19:35 
Reason for my vote of 4
good
GeneralReason for my vote of 5 very good thanksmemberfredatcodeproject13 Sep '11 - 2:00 
Reason for my vote of 5
very good
thanks
GeneralReason for my vote of 5 Good workmemberPravin Patil, Mumbai12 Sep '11 - 21:12 
Reason for my vote of 5
Good work
GeneralYou were right. The copy and paste was wrong. You've earned ...memberNik6619 Apr '11 - 23:06 
You were right. The copy and paste was wrong. You've earned a five! Smile | :)
GeneralRe: Thank you for verifying this. :)memberwmjordan22 Apr '11 - 1:52 
Thank you for verifying this. Smile | :)
GeneralI found very interesting your article and tried it. But I ca...memberNik6618 Apr '11 - 23:45 
I found very interesting your article and tried it. But I can not get it to work. Exit with an error 1. Unfortunately I do not know well cscripts.exe and are not able to understand.
I also tried the prompt and the error is as follows:

C:\ASP\RPBWDA\RPBWDA>cscript AutoIncrementBuildNumber.js Properties\AssemblyInfo.cs
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
C:\ASP\RPBWDA\RPBWDA\AutoIncrementBuildNumber.js (1, 8) Compile error of Microsoft JScript: Expected ';'
GeneralRe: I've tested the code and found nothing wrong. It might due t...memberwmjordan19 Apr '11 - 0:29 
I've tested the code and found nothing wrong.
It might due to wrong encoding. If you save the script file with the Unicode + BOM (byte order mark) encoding, the "Compile error" will occur. You shall save the js file with the ANSI encoding.
 
If you have fixed the problem, please revote this article.
GeneralReason for my vote of 5 Very cool; and extensible.memberSBJ1 Mar '11 - 7:46 
Reason for my vote of 5
Very cool; and extensible.
GeneralWhy not use Build Version Increment (http://autobuildversion...memberAnsgar Hellwig28 Feb '11 - 21:39 
Why not use Build Version Increment (http://autobuildversion.codeplex.com/)?
GeneralRe: Thanks for sharing the information. Actually I've checked ou...memberwmjordan2 Mar '11 - 1:22 
Thanks for sharing the information. Actually I've checked out AutoBuildVersion before doing this. Yet, this solution is simple and does the job for me as well.
The most critical issue for me is that I am playing with Visual C# Express which does not support add-ins at all. ^_^!
Now I am playing a little more with scripting in the post-build event, such as copying released programs and other files to a specific place, then use 7-zip to package those files--yep, I know there are installation programs out there too, but my application is very simple and people like portable ones, thus 7-zip is used.
Generalnice solution for common problem - i like it!memberjohannesnestler26 Feb '11 - 4:13 
nice solution for common problem - i like it!
QuestionTFS?memberrkb10 Oct '11 - 9:13 
We use TFS for version control so the AssemblyInfo.cs file is read-only. So I am having two problems implementing this solution. 1) I am not sure of the JavaScript syntax needed to check this file out. 2)If the file is checked out and back in with version and description changed won't the modification time be changed and thus subverting the modification time change that was put in to prevent rebuilds?
 
Thank you.
 
Kevin Burton
rkevinburton@charter.net
AnswerRe: TFS?memberwmjordan10 Oct '11 - 21:40 
When using concurrent version system, you may have the version number controlled in one place rather than everybody is modifying it, since many people may change part of the code, hence the version number should only change when the whole project is merged and release.
 
I am not familiar with TFS. If the build process is run on the server, then the script can still do its job. Whether the modification time is changed depends on the script. At the usual case, the modification time of the AssemblyInfo.cs file is changed when the build number is incremented.
 
If the build process is not done on the server but a special machine, you may have to manually check out that file on that machine. The code file which contains the version number is not necessary named AssemblyInfo.cs. To bypass the read-only limitation of AssemblyInfo.cs, you can put the AssemblyVersion attribute on another file and have it compiled with the project.
GeneralAutomatic version numbermemberRosenne18 Apr '11 - 22:55 
The "very large version number" is actually a representation of the date and time the program was built, and as such is more useful than a simple running number.
 
See "C# .Net : How works automatic assembly versioning"[^]
GeneralRe: Automatic version numbermemberwmjordan19 Apr '11 - 0:41 
Thank you for the information. However, the "Very large version" is not that simple to understand by a human and it even requires a computer aided conversion, which is a bit too tricky.
If the purpose is to embed the build date and time into the number, why not use a more understandable format like "
1.0.1104.1702
" (the build and revision number means the 2nd build on 11-04-17) or "
1.0.10417.1835
" (the build and revision number means 11-04-17 18:35)?
With my script, it is not so difficult to achieve this, and every body knows the build date and time at their first sight.
GeneralNice; you got my 5memberSBJ1 Mar '11 - 7:48 
Very cool; and easily extensible.
GeneralRe: Nice; you got my 5memberwmjordan2 Mar '11 - 1:57 
Thank you for your five.
And this add-in (http://autobuildversion.codeplex.com/) has hinted me that year, month, day, etc. can be used in the build numbers too, which is also easy to implement with Javascript.
var t = new Date();
var ts = t.getYear().toString().substr(2) + (t.getMonth()+101).toString().substr(1) + (100+t.getDate()).toString().substr(1);
// ts = DateTime.Now.ToString("YYMMDD")

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 2 Oct 2011
Article Copyright 2011 by wmjordan
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid