Click here to Skip to main content
15,512,456 members
Articles / Web Development / ASP.NET
Article
Posted 25 Nov 2008

Stats

240.9K views
4.9K downloads
118 bookmarked

How To Update Assembly Version Number Automatically

Rate me:
Please Sign up or sign in to vote.
4.46/5 (37 votes)
28 Jan 2009CPOL2 min read
A small utility which allows to modify AssemblyVersion attribute specified in AssemblyInfo.cs files

The Problem

I suppose I am not the only one who does not like the version numbers automatically generated by Visual Studio when you specify something like the following in your AssemblyInfo.cs file:

C#
[assembly: AssemblyVersion("2.7.*.*")] 

In the other hand, I would like to specify those numbers automatically during the build process. Moreover it would be great to have an ability to change the whole version number or just increase the latest part of it (build number).  

Of course, you may say that such an operation can simply be done manually. It is true for one or two assemblies. But our usual project contains about 10-15 different assemblies and we would like to have a version number in all of them synchronized.

The Solution

So we need some utility which will perform all the described tasks automatically and which we can call from our build script. The presented simple program allows to change the whole version number in AssemblyInfo files or just increase the number of the build.

To use this program, just call AssemblyInfoUtil.exe with two parameters. The first parameter is the path to AssemblyInfo.cs file that you would like to modify. The second parameter tells the program how to modify the version number attribute. It can be one of the following options:

-set:<New Version Number>

Set the version number to the specified one.

-inc:<Parameter Index>

Simply increase the number of one parameter in version string by 1. Here "Parameter Index" can be any number from 1 to 4. For 1 - the major version number will be increased, for 2 - the minor one and so on.

Examples

plain
AssemblyInfoUtil.exe -set:3.1.7.53 "C:\Program Files\MyProject1\AssemblyInfo.cs"

Set the version string to "3.1.7.53".

plain
AssemblyInfoUtil.exe -inc:4 AssemblyInfo.cs

Increase the last (revision) number. So in our case it will become 54.

The Code

So here is the code of this utility. I have published only the content of the Main.cs file. Other project files (like *.csprj) can be found in the attached archive.

C#
using System;
using System.IO;
using System.Text;

namespace AssemblyInfoUtil
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class AssemblyInfoUtil
    {
	private static int incParamNum = 0;

	private static string fileName = "";
	
	private static string versionStr = null;

	private static bool isVB = false;

	/// <summary>
	/// The main entry point for the application.
	/// </summary>
	[STAThread]
	static void Main(string[] args)
	{
	    for (int i = 0; i < args.Length; i++) {
	        if (args[i].StartsWith("-inc:")) {
		   string s = args[i].Substring("-inc:".Length);
		   incParamNum = int.Parse(s);
	        }
	        else if (args[i].StartsWith("-set:")) {
		   versionStr = args[i].Substring("-set:".Length);
	        }
	        else
		   fileName = args[i];
	    }

	    if (Path.GetExtension(fileName).ToLower() == ".vb")
		isVB = true;

	    if (fileName == "") {
		System.Console.WriteLine("Usage: AssemblyInfoUtil 
		    <path to AssemblyInfo.cs or AssemblyInfo.vb file> [options]");
		System.Console.WriteLine("Options: ");
		System.Console.WriteLine("  -set:<new version number> - 
				set new version number (in NN.NN.NN.NN format)");
		System.Console.WriteLine("  -inc:<parameter index>  - 
		   increases the parameter with specified index (can be from 1 to 4)");
		return;
	    }

	    if (!File.Exists(fileName)) {
		System.Console.WriteLine
			("Error: Can not find file \"" + fileName + "\"");
		return;
	    }

	    System.Console.Write("Processing \"" + fileName + "\"...");
	    StreamReader reader = new StreamReader(fileName);
             StreamWriter writer = new StreamWriter(fileName + ".out");
	    String line;

	    while ((line = reader.ReadLine()) != null) {
		line = ProcessLine(line);
		writer.WriteLine(line);
	    }
	    reader.Close();
	    writer.Close();

	    File.Delete(fileName);
	    File.Move(fileName + ".out", fileName);
	    System.Console.WriteLine("Done!");
	}

	private static string ProcessLine(string line) {
	    if (isVB) {
		line = ProcessLinePart(line, "<Assembly: AssemblyVersion(\"");
		line = ProcessLinePart(line, "<Assembly: AssemblyFileVersion(\"");
	    } 
	    else {
		line = ProcessLinePart(line, "[assembly: AssemblyVersion(\"");
		line = ProcessLinePart(line, "[assembly: AssemblyFileVersion(\"");
	    }
	    return line;
	}

	private static string ProcessLinePart(string line, string part) {
	    int spos = line.IndexOf(part);
	    if (spos >= 0) {
		spos += part.Length;
		int epos = line.IndexOf('"', spos);
		string oldVersion = line.Substring(spos, epos - spos);
		string newVersion = "";
		bool performChange = false;

		if (incParamNum > 0) {
	  	    string[] nums = oldVersion.Split('.');
		    if (nums.Length >= incParamNum && nums[incParamNum - 1] != "*") {
			Int64 val = Int64.Parse(nums[incParamNum - 1]);
			val++;
			nums[incParamNum - 1] = val.ToString();
			newVersion = nums[0]; 
			for (int i = 1; i < nums.Length; i++) {
			    newVersion += "." + nums[i];
			}
			performChange = true;
		    }
		}
		
		else if (versionStr != null) {
		    newVersion = versionStr;
		    performChange = true;
		}

		if (performChange) {
		    StringBuilder str = new StringBuilder(line);
		    str.Remove(spos, epos - spos);
		    str.Insert(spos, newVersion);
		    line = str.ToString();
		}
	    } 
	    return line;
	}
     }
}

History

  • 25th November, 2008: Initial post
  • 27th January, 2009: Article update

License

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


Written By
Founder Korzh.com
Ukraine Ukraine
Software developer and entrepreneur.

Main projects:
* EasyQuery - ad-hoc data filtering UI for .NET applications;
* Localizer - localization tool kit for Delphi projects;

Comments and Discussions

 
GeneralMy vote of 5 Pin
David A. Gray18-Jun-22 21:50
David A. Gray18-Jun-22 21:50 
GeneralMy vote of 5 Pin
mishrsud5-Sep-16 21:04
professionalmishrsud5-Sep-16 21:04 
QuestionI had modified to allow change InstallShield LE setup Pin
gemese7-Nov-15 7:31
gemese7-Nov-15 7:31 
Hi,
Thanks a lot for your programming experience and the automatic versioning, but i also need to modify the install shield LE setup.

I the other hand, i need to update the version number, but always in automatic, despite the index.

In main() function i added:
C#
if (Path.GetExtension(fileName).ToLower() == ".isl")
    isInstallShield = true;


In the ProcessLine() fucntion i added:
XML
else if (isInstallShield)
{
    line = ProcessInstallShieldLinePart(line, "<row><td>ProductVersion</td><td>");
    line = ProcessInstallShieldLinePart(line, "}</td><td></td><td>");
    line = ProcessInstallShieldLineProductCode(line, "ProductCode</td><td>{");
}


At your ProcessLinePart() function i added some code of the following function to avoid using -inc or the update index.

C#
private static string ProcessInstallShieldLinePart(string line, string part)
{
    int spos = line.IndexOf(part);

    if (spos >= 0)
    {
        spos += part.Length;
        int epos = line.IndexOf('<', spos);
        string oldVersion = line.Substring(spos, epos - spos);
        string newVersion = "";
        bool performChange = false;

        if (incParamNum > 0)
        {
            string[] nums = oldVersion.Split('.');
            if (nums.Length >= incParamNum && nums[incParamNum - 1] != "*")
            {
                Int64 val = Int64.Parse(nums[incParamNum - 1]);
                val++;
                nums[incParamNum - 1] = val.ToString();
                newVersion = nums[0];
                for (int i = 1; i < nums.Length; i++)
                {
                    newVersion += "." + nums[i];
                }
                performChange = true;
            }

        }
        else if (versionStr != null)
        {
            newVersion = versionStr;
            performChange = true;
        }
        else
        {
            //If the command line parameters do not specify the index, lets begin to update all the version number, starting with the revision(0.0.0.x) until the mayor version(x.0.0.0)
            //  the max number is 65534 for each.
            // When the revision reach the 65534, then start again in 0, and the Build Number add one and so on.

            //      Major Version
            //      Minor Version
            //      Build Number
            //      Revision

            string[] nums = oldVersion.Split('.');
            bool bolUpdateNext = true; //Always true at the begining to change the revision first.

            if (nums.Length >= 3 && nums[2] != "*") //Avoid changing the example of Visual Studio.
            {
                Int64 val = -1;

                for (int i = nums.Length; i > 0; i--)
                {
                    Int64.TryParse(nums[i - 1], out val);

                    if (bolUpdateNext)
                    {
                        val++;
                        bolUpdateNext = false;
                    }

                    if (val >= 65534)
                    {
                        val = 0;
                        bolUpdateNext = true;
                    }

                    if (string.IsNullOrEmpty(newVersion))
                    {
                        newVersion = val.ToString();
                    }
                    else
                    {
                        newVersion = val + "." + newVersion;
                    }


                }

                performChange = true;
            }

        }

        if (performChange)
        {
            StringBuilder str = new StringBuilder(line);
            str.Remove(spos, epos - spos);
            str.Insert(spos, newVersion);
            line = str.ToString();
        }
    }
    return line;
}



And now the InstallShield LE producto code to allow the installation to update the previous instalations.

C#
private static string ProcessInstallShieldLinePart(string line, string part)
{
    int spos = line.IndexOf(part);

    if (spos >= 0)
    {
        spos += part.Length;
        int epos = line.IndexOf('<', spos);
        string oldVersion = line.Substring(spos, epos - spos);
        string newVersion = "";
        bool performChange = false;

        if (incParamNum > 0)
        {
            string[] nums = oldVersion.Split('.');
            if (nums.Length >= incParamNum && nums[incParamNum - 1] != "*")
            {
                Int64 val = Int64.Parse(nums[incParamNum - 1]);
                val++;
                nums[incParamNum - 1] = val.ToString();
                newVersion = nums[0];
                for (int i = 1; i < nums.Length; i++)
                {
                    newVersion += "." + nums[i];
                }
                performChange = true;
            }

        }
        else if (versionStr != null)
        {
            newVersion = versionStr;
            performChange = true;
        }
        else
        {
            //If the command line parameters do not specify the index, lets begin to update all the version number, starting with the revision(0.0.0.x) until the mayor version(x.0.0.0)
            //  the max number is 65534 for each.
            // When the revision reach the 65534, then start again in 0, and the Build Number add one and so on.

            //      Major Version
            //      Minor Version
            //      Build Number
            //      Revision

            string[] nums = oldVersion.Split('.');
            bool bolUpdateNext = true; //Always true at the begining to change the revision first.

            if (nums.Length >= 3 && nums[2] != "*") //Avoid changing the example of Visual Studio.
            {
                Int64 val = -1;

                for (int i = nums.Length; i > 0; i--)
                {
                    Int64.TryParse(nums[i - 1], out val);

                    if (bolUpdateNext)
                    {
                        val++;
                        bolUpdateNext = false;
                    }

                    if (val >= 65534)
                    {
                        val = 0;
                        bolUpdateNext = true;
                    }

                    if (string.IsNullOrEmpty(newVersion))
                    {
                        newVersion = val.ToString();
                    }
                    else
                    {
                        newVersion = val + "." + newVersion;
                    }


                }

                performChange = true;
            }

        }

        if (performChange)
        {
            StringBuilder str = new StringBuilder(line);
            str.Remove(spos, epos - spos);
            str.Insert(spos, newVersion);
            line = str.ToString();
        }
    }
    return line;
}


When you need to update all the stuff, lets use the Pre/Post-Build events.

For AssemblyInfo.cs
SQL
Adding this lines to the BuildEvents/Pre-build event command line, the system will automatically change the revision numbers only in Release build.
if $(ConfigurationName) == Release (
"D:\Desarrollo\Personales\!ProyectosGlobales\AssemblyInfoUtilSource\bin\Release\AssemblyInfoUtil.exe" "D:\Desarrollo\Personales\FILE_MAINTENANCE\WIA_FILE_MAINTENANCE\Properties\AssemblyInfo.cs"
)



For InstallShield<setup>.isl
SQL
Adding this lines to the BuildEvents/Post-build event command line, the system will automatically change the revision numbers only in Release build for the InstallShield LE.
if $(ConfigurationName) == Release (
"D:\Desarrollo\Personales\!ProyectosGlobales\AssemblyInfoUtilSource\bin\Release\AssemblyInfoUtil.exe" "D:\Desarrollo\Personales\FILE_MAINTENANCE\InstallShieldFileMaintenance\InstallShieldFileMaintenance.isl"
)

GeneralHelp me lot Pin
panditvishal884-May-15 20:41
panditvishal884-May-15 20:41 
SuggestionJust an improvement Pin
Thyrador10-Jun-14 23:58
Thyrador10-Jun-14 23:58 
GeneralRe: Just an improvement Pin
BostjanSkok6-Nov-14 8:12
BostjanSkok6-Nov-14 8:12 
GeneralRe: Just an improvement Pin
Sergiy Korzh6-Nov-14 10:55
professionalSergiy Korzh6-Nov-14 10:55 
GeneralMy vote of 5 Pin
DeadlyEmbrace2-Sep-13 23:47
DeadlyEmbrace2-Sep-13 23:47 
GeneralMy Vote of 5 Pin
Member 101962197-Aug-13 12:52
Member 101962197-Aug-13 12:52 
GeneralMy vote of 5 Pin
rickist22-Nov-12 5:48
rickist22-Nov-12 5:48 
GeneralMy vote of 5 Pin
_jazz22-Jun-12 2:43
_jazz22-Jun-12 2:43 
SuggestionMake it fully automatic with build events Pin
_jazz22-Jun-12 2:33
_jazz22-Jun-12 2:33 
QuestionThank you for sharing Pin
mikeperetz14-Mar-12 3:28
mikeperetz14-Mar-12 3:28 
SuggestionVersioning Controlled Build Pin
TobiasP7-Mar-12 6:58
TobiasP7-Mar-12 6:58 
AnswerThanks a lot Pin
Sudarsan Srinivasan13-Apr-11 1:39
Sudarsan Srinivasan13-Apr-11 1:39 
GeneralBig thanks man Pin
=Quaqmire=13-Mar-11 17:55
=Quaqmire=13-Mar-11 17:55 
GeneralMy vote of 5 Pin
lparkd4-Oct-10 6:33
lparkd4-Oct-10 6:33 
GeneralWorks great for me Pin
Michael Elly10-Aug-10 13:52
Michael Elly10-Aug-10 13:52 
GeneralMy vote of 5 Pin
Michael Elly10-Aug-10 13:49
Michael Elly10-Aug-10 13:49 
GeneralTry using regular expressions to parse Pin
mekansm29-Jan-09 7:37
mekansm29-Jan-09 7:37 
GeneralSynchronize version number across assemblies Pin
Marc Scheuner29-Jan-09 3:52
professionalMarc Scheuner29-Jan-09 3:52 
GeneralRe: Synchronize version number across assemblies Pin
Don DenUyl3-Feb-09 4:10
Don DenUyl3-Feb-09 4:10 
GeneralNice article Pin
Jeffrey Cameron27-Jan-09 6:04
Jeffrey Cameron27-Jan-09 6:04 
GeneralRe: Nice article Pin
Sergiy Korzh27-Jan-09 21:41
professionalSergiy Korzh27-Jan-09 21:41 
QuestionHow To Update Assembly Version Number Automatically Pin
SergiuMD20-Jan-09 23:14
SergiuMD20-Jan-09 23:14 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.