Featured Post

Organize and rename photos by EXIF data with PowerShell

This PowerShell script organizes and renames all photos in a selected folder using EXIF data. It will also create thumbnails of the images i...

Wednesday, October 23, 2013

Visual Studio Pre-Build Event Script to Automatically Incremement Version Number

Using this post you will be able to change Visual Studio to 'Release Mode' and by building the project it runs a batch script which will prompt you for what version you want to set in the assembly files before building the project. The choices are No Change, Auto Increment, or Manually entering the build you want to use. This allows you to skip the prompt if you use 'Debug' mode, which will build using the existing version.

Right click project, select Properties > Build Events

In the "Pre-build event command line" box, put the following:

if "$(ConfigurationName)" == "Release" start "Version" /D "$(SolutionDir)" /WAIT Version.bat

There are 3 files to make this work, these files need a Solution Folder to reside in:

Right click solution, select Add > New Solution Folder

Now, create these 3 files:

Version.bat - Executed by Visual Studio pre-build event

@powershell -ExecutionPolicy Unrestricted -File "%~dp0Version.ps1"

For more information on the variable %~dp0 click here

Version.txt - Your starting version number

1.0.0.0

Version.ps1 - PowerShell script that is executed by Version.bat which actually increments Version number where needed

param (
    [string]$mode = "debug"
)

Write-Host "##########################"
Write-Host "# Version.ps1"
Write-Host "##########################"
Write-Host "#"
Write-Host "# This script will increment (if chosen) and set the version number in the"
Write-Host "# appropriate assembly files throughout the project before compiling continues"
Write-Host "#"
Write-Host "##########################"
Write-Host ""

trap
{
    Write-Error $_
    exit 1
}

################
# Example Script Usage
################
# @powershell -ExecutionPolicy Unrestricted -File "%~dp0Version.ps1"

####################
# Example Method Usage
####################

# Set-VersionFile -File $versionFilePath -Version $newVersion
# Set-VersionInAssemblyInfo -File ($scriptDirectory + "\ProfitPOS\Properties\AssemblyInfo.cs") -Version $newVersion
# Set-VersionInAssemblyInfo -File ($scriptDirectory + "\..\BootstrapperCustom\Properties\AssemblyInfo.cs") -Version $newVersion
# Set-VersionInWixGlobal -File ($scriptDirectory + "\..\Setup\Variables.wxi") -Version $newVersion
# Set-VersionInAssemblyReference -File ($scriptDirectory + "\MyProduct.Assembly3\App.config") -AssemblyName "MyProduct.Assembly2" -Version $newVersion
# Set-VersionInBindingRedirect -File ($scriptDirectory + "\MyProduct.Assembly4\Web.config") -AssemblyName "Other.Component" -Version $otherVersion

##########
# Methods
##########

function Update-Version ([Version]$Version)
{
    $date = (Get-Date).ToUniversalTime()
    #$newBuild = $date.ToString("yyMM")
    #$dayRevisionMin = $date.Day * 1000
    #if (($Version.Build -lt $newBuild) -or ($Version.Revision -lt $dayRevisionMin)) { $newRevision = $dayRevisionMin + 1 } else { $newRevision = $Version.Revision + 1 }

 # This forces new build each time for major upgrades to work, revision is ignored by windows installer
 $newBuild = $Version.Build + 1
 #$newRevision = $date.ToString("HHMMss") / 4
 $newRevision = $Version.Revision

    New-Object -TypeName System.Version -ArgumentList $Version.Major, $Version.Minor, $newBuild, $newRevision
}
 
function Get-VersionFile ([String]$File)
{
    #Write-Host ("Reading version file " + $File)
    #Write-Host ""
    $versionString = [System.IO.File]::ReadAllText($File).Trim()
    New-Object -TypeName System.Version -ArgumentList $versionString
}
 
function Set-VersionFile ([String]$File, [Version]$Version)
{
    #Write-Host ("Writing version file " + $File)
    #Write-Host ""
    [System.IO.File]::WriteAllText($File, $Version.ToString())
}
 
function Set-VersionInAssemblyInfo ([String]$File, [Version]$Version)
{
    Write-Host ("Setting version in assembly info file " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $contents = [RegEx]::Replace($contents, "(AssemblyVersion\("")(?:\d+\.\d+\.\d+\.\d+)(""\))", ("`${1}" + $Version.ToString() + "`${2}"))
    $contents = [RegEx]::Replace($contents, "(AssemblyFileVersion\("")(?:\d+\.\d+\.\d+\.\d+)(""\))", ("`${1}" + $Version.ToString() + "`${2}"))
    [System.IO.File]::WriteAllText($File, $contents)
}
 
function Set-VersionInWixGlobal ([String]$File, [Version]$Version)
{
    Write-Host ("Setting version in WIX global file " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $contents = [RegEx]::Replace($contents, "(\<\?define\s*ProductVersion\s*=\s*"")(?:\d+\.\d+\.\d+\.\d+)(""\s*\?\>)", ("`${1}" + $Version.ToString() + "`${2}"))
    [System.IO.File]::WriteAllText($File, $contents)
}
 
function Set-VersionInAssemblyReference ([String]$File, [String]$AssemblyName, [Version]$Version)
{
    Write-Host ("Setting version in assembly references of " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $contents = [RegEx]::Replace($contents, "(["">](?:\S+,\s+){0,1}" + $AssemblyName + ",\s+Version=)(?:\d+\.\d+\.\d+\.\d+)([,""<])", ("`${1}" + $Version.ToString() + "`${2}"))
    [System.IO.File]::WriteAllText($File, $contents)
}
 
function Set-VersionInBindingRedirect ([String]$File, [String]$AssemblyName, [Version]$Version)
{
    Write-Host ("Setting version in binding redirects of " + $File)
    Write-Host ""
    $contents = [System.IO.File]::ReadAllText($File)
    $oldVersionMax = New-Object -TypeName "System.Version" -ArgumentList $Version.Major, $Version.Minor, $Version.Build, ($Version.Revision - 1)
    $pattern = "([\s\S]*?<assemblyIdentity\s+name=""" + $AssemblyName + """[\s\S]+?/>[\s\S]*?<bindingRedirect\s+oldVersion=""\d+\.\d+\.\d+\.\d+-)(?:\d+\.\d+\.\d+\.\d+)(""\s+newVersion="")(?:\d+\.\d+\.\d+\.\d+)(""[\s\S]*?/>)"
    $contents = [RegEx]::Replace($contents, $pattern, ("`${1}" + $oldVersionMax.ToString() + "`${2}" + $Version.ToString() + "`${3}"))
    [System.IO.File]::WriteAllText($File, $contents)
}

########
# Begin
########
$scriptDirectory =  [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition)
$versionFilePath = $scriptDirectory + "\Version.txt"

$oldVersion = Get-VersionFile -File $versionFilePath
$newVersion = Update-Version -Version $oldVersion

Write-Host ("[Enter] for Current Version: " + $oldVersion.ToString());
Write-Host ""
Write-Host ("[B] for New Build Version: " + $newVersion.ToString());
Write-Host ""
Write-Host "Or enter a Custom Version, example: 1.2.3.4";
Write-Host ""
Write-Host ""

$mode = Read-Host "Which version do you want to use?"
Write-Host ""

if ($mode.ToLower().Contains("b"))
{
    Write-Host ""
    Write-Host ("Using New Build Version: " + $newVersion.ToString())
}
elseif ($mode.length -lt 1)
{
    $newVersion = $oldVersion
    Write-Host ""
    Write-Host ("Using Current Version: " + $newVersion.ToString())
}
else
{
    $modes = $mode.Split(".")
    $newVersion = New-Object -TypeName System.Version -ArgumentList $modes[0], $modes[1], $modes[2], $modes[3]
    Write-Host ""
    Write-Host ("Using Custom Version: " + $newVersion.ToString())
}
    
Write-Host ""
Write-Host ""

Set-VersionFile -File $versionFilePath -Version $newVersion
Set-VersionInAssemblyInfo -File ($scriptDirectory + "\ProfitPOS\Properties\AssemblyInfo.cs") -Version $newVersion
Set-VersionInAssemblyInfo -File ($scriptDirectory + "\..\BootstrapperCustom\Properties\AssemblyInfo.cs") -Version $newVersion
Set-VersionInWixGlobal -File ($scriptDirectory + "\..\Setup\Variables.wxi") -Version $newVersion

Write-Host ""
Write-Host "Done!"
Write-Host ""

Read-Host "Hit enter to exit"
exit 0

1 comment: