I finally got around to setting up a descriptive versioning of my BizTalk assemblies the other day. What I wanted was to have something that made it possible to trace different versions of the assemblies back to the sourcecode. And to make it easily visible that an assembly had changed. I took it one step further and came up with an easy to implement way of showing which versions of code is deployed on the servers.
The build process
I build the entire solution, using an MSBUILD script, that handles copying dll’s to an output folder on a drop share. I then deploy assemblies using powershell and the BizTalk Powershell Provider. I have a full deploy script that tears down the applications and recreates them, and a “hotfix” deployment that have a minimal impact on running applications. I don’t particularly like MSI package deployments for BizTalk as IMO they add a “fog of war” to the deployment. Especially when something goes wrong. I know some might consider such an “xcopy deployment” of DLL’s to be medieval, but there is a transparency to what is happening, and the end result is the same. My binding files are created using the XMLPreprocesor / excel spreadsheet method.
I don’t currently need to update the AssemblyVersion with all the problems of updating references in maps and orchestrations etc. If you should go there, make sure to look at the documentation. I only need to update the AssemblyFileVersion to communicate the versioning of applications. The AssemblyFileVersion will show up as displayed here on another windows file:

all the build artifacts are stored in a separate empty Class project as part of the solution. A project that I exclude from the solution build configuration. All the scripts and the build file shown below are part of that project.
Incrementing the Build number
To add some value to the version number I wanted to add the SVN revision number to identify the assembly back to my sourcecode revision.
The client I currently work for uses SVN, my favorite easy to use and understand source control system. (I still think GIT is overly complicated and I rarely need my code to be social anyway).
For this I use the MSBuild Community Tasks and the SvnVersion Task, added to the solution through Nuget like this:
Install-Package msbuildtasks
In the MSBuild script I reference the SvnVersion and the FileUpdate tasks like this:
<UsingTask TaskName="SvnVersion" AssemblyFile="..\.build\MSBuild.Community.Tasks.dll" />
<UsingTask TaskName="FileUpdate" AssemblyFile="..\.build\MSBuild.Community.Tasks.dll" />
In a separate target in the MSbuild file, I update my assemblyfileversion template with the SVN revision number
<Target Name="SubVersionBeforeBuildVersionTagItUp" DependsOnTargets="BeforeBuild">
<ItemGroup>
<AssemblyInfoFiles Include="$(ProjectDir)\**\*AssemblyInfo.cs" />
</ItemGroup>
<SvnVersion LocalPath="$(MSBuildProjectDirectory)" ToolPath="$(SVNToolPath)">
<Output TaskParameter="Revision" PropertyName="MySubVersionRevision" />
</SvnVersion>
<FileUpdate Files="AssemblyFileInfo.cs"
Regex="(AssemblyFileVersion\(\")(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText="$1$2.$3.$4.$(MySubVersionRevision)" />
</Target>
I make sure to ONLY update the AssemblyFileVersion and not the AssemblyVersion number, which I leave at 1.0.0.0 - this is handled by the regular expression in the <FileUpdate> section of the build target.
Now I don’t want to check in the now changed AssemblyVersion files, so what I do is to store a Template of the AssemblyFileVersion.cs in SVN. I do this in my build project, and this is referenced as a linked file, in my other Visual Studio projects.
I split the version properties out into a separate AssemblyFileInfo.cs file as I have both BizTalk projects and C# class projects that I wanted to version. The AssemblyInfo.cs files for BizTalk projects have these declarations added to them, so I couldn’t just use the Assemblyinfo.cs file in a c# Class project.
using Microsoft.XLANGs.BaseTypes;
using Microsoft.BizTalk.XLANGs.BTXEngine;
[assembly: Microsoft.XLANGs.BaseTypes.BizTalkAssemblyAttribute(typeof(BTXService))]
Instead, I removed the two AssemblyVersion declarations from the original Assemblyinfo.cs and put hem into [Beskriv AssemblyFileVersion.cs.template]
using System.Reflection;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.1.2.179")]
Last – I add the AssemblyFileInfo.cs file to my other projects as a link. So I only need to update the AssemblyInfo.cs file in my build project.
I then chose to “Ignore” the AssemblyFileInfo.cs file from SVN, so I SVN ignore that it changes on every build.
Reporting on what is deployed
I wanted to produce something to make it easy to identify the version of assemblies that is deployed into the different environments. Something that could answer questions like: Is it the same version of assemblies deployed to production as there is to test? What revision of sourcecode does the assemblies relate to? And so on. I also “tag” a branch in SVN of the entire solution for any builds that I consider to be “Production worthy” to easily get at it, but that is a manual process.
To report on assembly versions, I opted for doing it at the end of a deployment, and to add to the PowerShell scripts that already did the deployment. I wanted something that looked at Biztalk and discovered all the assemblies that are included in my applications. I also wanted to produce a HTML document and to make it easily available, I chose to publish it to a local website on the server.
There is ample room for improvement on how to document this, but I like the idea of going to a URL, in a server for that specific environment, to check up on what is deployed there.
This PowerShell code could most likely be shorter and more effective, but it does the job. I like to write out the commands and not use abbreviations. Makes it easier to read IMO. Feel free to come up with suggestions for improvements to this code - I don't mind. As Scott Hanselman wrote. I am NOT my code. So I don’t take criticism of my code personally.
First I declare a funtion I use to get the assemblyversion and the assemblyfileversion numbers from an array of file-paths.
Then I load the BizTalk PowerShell provider, and then I look for the the BizTalk related assemblies in the BizTalk:\All Artifacts\Resources' folder.
$BizTalkAssemblies = get-childitem 'BizTalk:\All Artifacts\Resources'
Then I select to work with just the assemblies with names that contains text I know is part of my solution, through doing a “match” with some text I know is part of the namespace of my projects.
I then call the function declared earlier, and pipe output out to a HTML file, and feed it a CSS file that pretties up the result a little.
Get-AssemblyVersion -assemblies $BizTalkAssemblies | ConvertTo-Html -CssUri "BizTalkDocumentation.css" -Title "BizTalk Version information" |Out-File -FilePath C:\inetpub\wwwroot\default.html
At last I copy the file to a website I know I can use for documentation purposes, and I add a timestamp to the end of the HTML file to show when it was last updated.
Copy-Item BizTalkDocumentation.css C:\inetpub\wwwroot\BizTalkDocumentation.css -Force
Add-Content -Path C:\inetpub\wwwroot\default.html -Value "<br /> Last Updated: $(Get-Date -Format F)"
This produces an output like this:

Here is the entire Powershell script for reference:
function Get-AssemblyVersion ($assemblies)
{
foreach ($item in $assemblies)
{
if ($item.Name -MATCH 'FTC')
{
Get-Item $item.SourceLocation | ForEach-Object {
try {
$_ | Add-Member NoteProperty FileVersion ($_.VersionInfo.FileVersion)
$_ | Add-Member NoteProperty AssemblyVersion (
[Reflection.Assembly]::LoadFile($_.FullName).GetName().Version)
} catch {} $_
} | Select-Object Name,FileVersion,AssemblyVersion
}
}
} #End function
$BizTalkMgmtDBName = "BizTalkMgmtDB"
$sqlInstance = "localhost"
If ((Get-PSSnapin | Select-Object Name | Select-String "BizTalkFactory.Powershell.Extensions") -eq $null)
{
Write-Host "Adding PSSnapin as it was not there...`r"
$InitializeDefaultBTSDrive=$false
Add-PSSnapIn BizTalkFactory.PowerShell.Extensions
}
If (!(Test-Path -Path "BizTalk:\"))
{
Write-Host "Adding BizTalk:\ as it was not mounted ... With SqlInstance:`r " $sqlInstance
New-PSDrive -name BizTalk -PSProvider BizTalk -Root BizTalk:\ -instance $sqlInstance -database $BizTalkMgmtDBName
}
$BizTalkAssemblies = get-childitem 'BizTalk:\All Artifacts\Resources' #| % {$_.Name -match "FTC"}
Get-AssemblyVersion -assemblies $BizTalkAssemblies | ConvertTo-Html -CssUri "BizTalkDocumentation.css" -Title "BizTalk Version information" |Out-File -FilePath C:\inetpub\wwwroot\default.html
Copy-Item BizTalkDocumentation.css C:\inetpub\wwwroot\BizTalkDocumentation.css -Force
Add-Content -Path C:\inetpub\wwwroot\default.html -Value "<br /> Last Updated: $(Get-Date -Format F)"
If you are interested in the deployment and build files, let me know.
Missing stuff – not hard to implement, just haven’t gotten around to it yet:
- I still need to version and document the services that are deployed
- It would be great to have a history as well as the current snapshot, for that a db would probably be the right solution
- I would like for my BuildScript to also Automatically svn tag the current revision, every time I do a release build.
- Any other ideas for improvements?