I'm a huge fan of continuous integration and automated builds. I've written about MSBuild before and find myself using it a lot; mainly because it's familiar and build scripts aren't the sort of thing you have a lot of time to spend on. I've used MSBuild to increment version numbers before, every build having a different number is a good idea (MSDN, 2010). Previously I have written the build number that gets incremented into a text file containing only the number, so it is nice and easy to fetch.
Recently though I wanted to read the version (Major.Minor.Build.Revision) numbers from the assemblyInfo file into properties in my build script, so I could modify and use them as required. What follows is an MSBuild target that uses the MSBuild Community Tasks RegexMatch and RegexReplace tasks to do just that.
<ReadLinesFromFile File="$(VersionInfoFile)">
<Output TaskParameter="Lines" ItemName="IterationNumberFileContents"/>
</ReadLinesFromFile>
First we read all the lines from the versionInfoFile into a task item. I have a file that contains just the solution version with the other solution info properties in another file. This will work if this is a full solution info file though.
<RegexMatch Input="@(IterationNumberFileContents)" Expression="AssemblyVersion\(\"(\d+)\.(\d+)\.(\d+)\.(\d+)">
<Output ItemName="VersionNumberLineReturn" TaskParameter="Output"/>
</RegexMatch>
Next we use the RegexMatch task to find the string AssemblyVersion("X.X.X.X in the file (X's being any number). Note that we escape the parenthesis and quotes with a backslash as these have meaning in regular expressions. We wrap each digit selector in parenthesis (\d+) so that we can refer to it as a regular expression group. The .NET regular expression engine allows you to reference parts of the selection using back references (Goyvaerts, 2010). $0 represents the entire string matched (in our case AssemblyVersion("X.X.X.X ). $1 - $9 represent groups in the order they were matched. In our case $1 through - $4 represent the four version numbers.
<RegexReplace Input="@(VersionNumberLineReturn)" Expression="\[assembly\: (AssemblyVersion)\(\"(\d+)\.(\d+)\.(\d+)\.(\d+)\$(DOUBLE_QUOTES)\)\]" Replacement="$1" Count="1"><Output PropertyName="MajorNumber" TaskParameter="Output"/>
</RegexReplace>
This makes it easy to select out each version number into a property using these back references and the same regular expression. Above we are selecting the major version into the $(MajorVersion) property. I'm sure there is a more elegant way to do this than repeating the regular expression, but I don't know how to specify multiple outputs from the regexMatch/regexReplace tasks.
The full target which selects all four version numbers into properties is available to download
here (2.00 kb), I hope this saves you some time.
References: