Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Auto Increment Visual Studio 2005 version build and revision number on compile time

0.00/5 (No votes)
10 Mar 2006 1  
Auto increment Visual Studio 2005 version build and revision number on compile.

Introduction

In Visual Studio 2005, the version numbers don't auto increment when you build your project. Annoying? I think so. So, I set out to find a way to do it. I did find some sample bits of code on the net that said would do it, and while they did work to a point, they didn't work well, or at all.

So, I set out to write my own using what I learned from the tutorials.

Using the code

Create a Windows DLL project, doesn't have to be anything special. In the default class, put the following:

Imports System
Imports Microsoft.Build.Framework
Imports Microsoft.Build.Utilities

Namespace BuildTasks
    Public Class IncrementBuildNumber
        Inherits Task

        Dim m_AssemblyFileLocation As String 
        ' This is the Assembly file

        ' that has the version info.


        Public Overrides Function _
               Execute() As Boolean
            Try
                Return IncrementVersion()
            Catch ex As Exception
                Log.LogError(ex.Message)
                Return False
            End Try
        End Function 'Execute 


        <Required()> Public Property _
                AssemblyFileLocation() As String
            Get
                Return m_AssemblyFileLocation
            End Get
            Set(ByVal value As String)
                m_AssemblyFileLocation = value
            End Set
        End Property

        Private Function IncrementVersion() As Boolean

            Dim i As Integer
            Dim FileData() As String
            Dim s As String
            Dim Version As String
            Dim v() As String
            Dim ResetRevision As Boolean = True

            ' All the commented msgbox

            ' lines are for debugging.

            ' you don't need them.


            'If MsgBox("IncrementVersion Run on file " & _

                        m_AssemblyFileLocation & _
                        vbNewLine & _
                        vbNewLine & _
                        "Copy path to clipboard?", _
                        MsgBoxStyle.YesNo) = _
                        MsgBoxResult.Yes Then
            '    My.Computer.Clipboard.Clear()

            '    My.Computer.Clipboard.

            '        SetText(m_AssemblyFileLocation)

            'End If



            ' Ok, we have the assembly file, try to open it.

            If IO.File.Exists(m_AssemblyFileLocation) Then

                ' Set build number to the number

                ' of days that have passed since Jan 1 2000

                ' If you want to modifiy what

                ' the build number means or does,

                ' here is the place.

                Dim Major As Integer = 1
                Dim Minor As Integer = 0
                Dim BuildNumber As Integer = _
                   Math.Abs(DateDiff(DateInterval.Day, _
                   Now.Date, CType("JAN/01/2000", Date)))
                Dim Revision As Integer = 0

                'MsgBox("New build number = " & BuildNumber)


                Try
                    FileData = _
                      IO.File.ReadAllLines(m_AssemblyFileLocation)

                    'MsgBox("Read " & FileData.Length & _

                            " lines from " & m_AssemblyFileLocation)

                    If FileData.Length = 0 Then Exit Function
                    ' loop through each line

                    's and look for the version lines.

                    For i = 0 To FileData.Length - 1
                        s = FileData(i)
                        If s.Length > 2 Then
                            ' Look to see if it contains

                            ' one of the 2 version lines we want.

                            'VB: <Assembly: AssemblyVersion("0.0.0.0")> 

                            'VB: <Assembly: AssemblyFileVersion("0.0.0.0")> 

                            'C#: [assembly: AssemblyFileVersion("1.0.0.0")]

                            'C#: [assembly: AssemblyVersion("1.0.0.0")]

                            If Not s.Substring(0, 1) = "'" _
                              And Not s.Substring(0, 2) = "//" Then

                                If s.Contains("AssemblyVersion") _
                                      Or s.Contains("AssemblyFileVersion") Then

                                  'MsgBox("Target line " & s _

                                  '   & " found, parsing now.")


                                  ' Get the version from the line.

                                  ' we do this by getting the first

                                  ' " and losing everything before it.

                                  ' do the same after the next "

                                  ' everything left should be version info.

                                  Version = _
                                      Microsoft.VisualBasic.Right(s, _
                                      s.Length - s.IndexOf(Chr(34)) - 1)
                                  Version = _
                                      Microsoft.VisualBasic.Left(Version, _
                                      Version.IndexOf(Chr(34)))

                                  'MsgBox("Version found = " & Version)


                                  v = Version.Split(".")
                                  If v.Length >= 0 Then
                                      Major = Val(v(0))
                                  If v.Length >= 1 Then
                                      Minor = Val(v(1))
                                  If v.Length >= 2 Then
                                      ResetRevision = _
                                        (BuildNumber <> Val(v(2)))
                                  If v.Length >= 3 Then
                                      Revision = Val(v(3)) + 1

                                  ' ok, now that we have

                                  ' the version numbers in their variables

                                  ' it's time to update

                                  ' the build, if needed.

                                  If ResetRevision Then
                                      Revision = 1

                                  'MsgBox("Replacing version with " _

                                  '& Major & "." & Minor & "." & _

                                  'BuildNumber & "." & Revision)


                                  ' ok, update the original

                                  ' line from the array.

                                  FileData(i) = _
                                    FileData(i).Replace(Version, _
                                    Major & "." & Minor & "." & _
                                    BuildNumber & "." & Revision)

                                  'MsgBox("Filedata(" & i _

                                  '   & ") = " & FileData(i))

                                End If
                            End If
                        End If
                    Next

                    ' ok, rewrite the assembly info back

                    ' into the file, and let's home

                    ' the compiler picks it up

                    'MsgBox("writing all data back to file")

                    IO.File.WriteAllLines(m_AssemblyFileLocation, _
                                                        FileData)


                Catch ex As Exception
                    ' hrm. Error. Fail please.

                    MsgBox("ERROR! " & ex.Message, "Build Tasks")
                    Log.LogError(ex.Message)
                    Return False
                End Try
            End If

            ' return success

            Return True
        End Function

    End Class
End Namespace

Now... how do we use it? I mean, you have a wonderful DLL file now... but how is it applied to your project? Well, you need to first copy your DLL into the same folder as your project file. Do not confuse the "solution" file (.sln) with your project file (.vbproj) as they are not the same thing.

Once the file is copied, open the .vbproj file in Notepad or some other text editor, so you can see the raw info.

Add the following line to the project file after the <project> tag and before the first <propertygroup> tag.

<UsingTask TaskName="BuildTasks.IncrementBuildNumber" 
            AssemblyFile="BuildTask.dll" />

An example of one of my project files would look like this, then:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" 
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="BuildTasks.IncrementBuildNumber" 
     AssemblyFile="BuildTask.dll" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">
               Debug</Configuration>
    
    ...

Scroll on down till you find the <Target Name="BeforeBuild"> tag. It may be commented out; uncomment it out, and between the open and close tags, add the following:

<IncrementBuildNumber AssemblyFileLocation = 
    "$(MSBuildProjectDirectory)\My Project\AssemblyInfo.vb">
</IncrementBuildNumber>

Note! Make sure the path to your assembly file is correct. If it's not in the "My Projects" folder, make sure you adjust your line above to say where it is. The $(MSBuildProjectDirectory) variable will be replaced with the folder the .vbproj file is in. So if the assembly.vb file is in the same location, then do use any subfolder. By default, VS 2005 puts it in the "My Projects" folder and calls it AssemblyInfo.vb. For C#, it's AssemblyInfo.cs.

This DLL should work for both C# and VB projects, hell, it should for all VS projects... but I only tested it with C# and VB.

Save the project file and then open it in VS. Now, every time you build the project, VS will call the IncrementBuildNumber class in the DLL and execute the code in it. The code itself opens your assembly file, edits the version info, then saves it.

Because you are doing this in the "BeforeBuild" section, it will be done before you build. Neat eh?

Note: Some project files may not have the <Target Name="BeforeBuild"> tags. If this is the case, I usually just add them after the <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" /> line.

I.e.:

<Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
<Target Name="BeforeBuild">
  <IncrementBuildNumber AssemblyFileLocation=
           "$(MSBuildProjectDirectory)\AssemblyInfo.vb">
  </IncrementBuildNumber>
  </Target>
  <Target Name="AfterBuild">
  </Target>
</Project>

Points of Interest

Sometimes, the revision number will jump 2 or 3 numbers. I don't know why, I can only assume that something is not re-loading correctly or that the compiler is calling the DLL twice or more. I don't really care actually, so I never bothered trying to fix it.

Also, if you have the project properties window, or the assembly file open, the version may not increment. Again, I didn't care enough about something so minor to spend time trying to fix it. Feel free to let me know if you find out why.

History

  • 1.0.0.0 - initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here