I’ve been working with BizTalk since 2006r1 (the one without the handy WCF adapters). Since that time I’ve tried various community offerings to improve the deployment process. In 2008 I was working for a large retailer. In order to support parallel development for phased but overlapping releases (config management fun!), they had up to four different BizTalk groups each containing between two and four servers. At the time, we had approximately eighteen different BizTalk applications of varying complexity, running on each BizTalk group. As you can imagine, this made management of the binding file time consuming and difficult. I turned to Michael Stephenson’s BizTalk Configuration Management tool on CodePlex (http://configsettingstool.codeplex.com/) this was a great help since it allowed us to maintain all the settings for the bindings in a single SQL Server database.
Last year I joined a BizTalk development team where they were already using the BizTalk Deployment Framework (BTDF)(http://biztalkdeployment.codeplex.com/) along with BizTalk 2010 and TFS 2010. I was really pleased because I’d heard a lot about the BTDF but hadn’t previously found the time to work with it. Working with the deployment framework can be quite daunting initially because it provides so much functionality. Fortunately the existing team members we able to quickly answer my questions.
At the time, the deployment framework was being used in the “conventional” way:
- click the VS toolbar button for a quick deploy to developer’s local BizTalk environment
- click another VS toolbar button to create an MSI to be manually copied and deployed to servers
It was at this time “I had a dream!”. Wouldn’t it be great if a check-in of source code triggered a build, automated deployment and test of our BizTalk applications. Of course, this is not a very original dream and Continuous Integration for non-BizTalk applications is very common. Just to make the task more challenging, I wanted to keep the Build Server free of BizTalk and instead deploy to a remote two-node BizTalk server group (known as our “dev” group). If I could get this this to work then it should be easy to adapt so that the BizTalk application could be deployed to other environments higher up the food chain, namely “test”, “pre-prod” and, dare I say it; “prod”.
The required development / configuration can be broken up into three categories:
- BTDF configuration changes
- Creation of a custom TFS build template (xaml)
- Creation of Powershell scripts and server configuration to enable the remote execution of these scripts
BTDF Configuration Changes
When built with TFS, the folder structure is different to that when simply building from within Visual Studio. With a standard VS build you may have you may find your solution is c:\development\solution name\solution.sln. When TFS builds it first does a “get latest” of the source code into the build agent folder. The path for this is determined by the Build Agent’s “Working Directory”. This can be accessed Start\All Programs\Microsoft Team Foundation Server 2010\Team Foundation Administration Console. From the UI select Build Ahent Properties. Another dialog will be displayed enabling you to set the “Woking Directory” for any particular build agent. The default is as follows: $(SystemDrive)\Builds\$(BuildAgentId)\$(BuildDefinitionPath). The following table gives a comparison of various build paths for a Standard VS build and a TFS build where System Drive = “C”, BuildAgentId = “3” and BuildDefintionPath = "\Solution\OvernightBuild”
|Standard VS Build Structure |
TFS Build Structure
c:\builds\3\tfs project name\overnightbuild\sources\solution name\solution.sln
c:\builds\3\tfs project name\overnightbuild\sources\solution name\project name\project.btproj
c:\builds\3\tfs project name\overnightbuild\binaries\project.dll
The btdfproj file has an item group describing the location path for the binaries of the solution’s: Schemas, Components, Pipelines, Pipeline Components, Orchestrations and Transforms. We need to configure these item groups to select from the TFS build structure where a TFS build is being used.
An example of the ItemGroup describing the binary locations (pulled from the BizTalkDeploymentFramework.targets file) can be seen below (note this wouldn’t actually be needed since we’re are using the default name for the orchestrations assembly but I am showing it to illustrate the difference between this and the item group used when a TFS build):
We are able to override this by adding the item group into the solution’s btdfproj file as follows:
Note how this overriding group will only be used if the “TeamBuild” variable is true, explained in the TFS section.
For the BizTalk deployment framework to create Virtual Directories, it expects to find them in the folder $(RedistDir)\ProjectName\bin. With a TFS build, components of the virtual directory (e.g. .svc, .dll etc.) won’t be in the correct place.
In order to remedy this, it is necessary to override the “CustomRedist” target, as illustrated by the following example:
Note: the WebServiceBinFolderPath has been declared as a property at the top of the btdf file, as illustrated below:
Solutions are built by TFS using what are know as build definitions.
An example of the VS UI used to manage settings within a build definition can be seen below:
One critical item from the above page that must be set is the “Items to build”. When not using BTDF this would typically point include the project files for any dependent projects, then the .sln of the BizTalk solution to be built. However, for any automated BTDF build, the .btdfproj file must be appended to the list of projects / solutions that need to be built.
From the previous screen grab, notice the pane labelled “Build process template”. This points to a .xaml windows workflow file which I have adapted from a standard build template.
One critical change can be seen in the following screen grab:
Note the condition that has been added to determine if the particular loop iteration is dealing with a btdfproj. If not then MS build is called in the normal way. However, if it has been requested to build a btdfproj then the following are passed as arguments to msbuild:
The critical parameter is TeamBuild, this use for this is explained in the section “BTDF Configuration Changes”
After the required assemblies have been built (into the binaries folder rather than \bin), then next tasks are:
- package the assemblies into MSIs
- copy the MSIs to the target BizTalk servers
- undeploy any existing installation of the BizTalk application
- deploy the new installation of the BizTalk application
In order to achieve this, a couple of custom Powershell script are called from the build xaml, one for the undeploy and another for the deploy. These can be seen in the following screen grab:
In order for these Powershell scripts to be generic, so that they can be used for any BizTalk application, it has been necessary to create many custom arguments that can be passed into the xaml execution and then passed from here into the Powershell scripts. These custom arguments are defined from a section at the base of the xaml designer window, as can be seen in the following screen grab:
Any argument defined in the xaml designer will become available on the build definition UI, once the xaml has been selected as the required build template. In the following screen grab, notice how the “ApplicationNameInBizTalk” argument has been made available to be configured for the build definition
The Powershell Scripts
As described in the previous section, toward the end of the xaml build execution Powershell is called to undeploy then deploy the BizTalk application.
The sequence of events required to achieve this are illustrated in the following diagram:
An illustration of the required Powershell scripts, their functions and organisation can be seen below:
Enabling Powershell Remoting
The two main Powershell scripts (UndeployBizTalkApp.ps1 and DeployBizTalkApp.ps1) will be started from the build server. However, they must execute script on the target BizTalk servers. In order to support this, the Build server must be configured as a Powershell Client and granted permission to pass credentials to the BizTalk servers. The initial request to Powershell will be made by the TFS Build Service. The credentials of this service will be passed to the BizTalk server. It’s important that the account used for the TFS Build service has is a member of the BizTalk administrators group.
The following steps are required to enable Powershell remoting between the Build Server and BizTalk Servers:
- On the Build Server execute the following from a Powershell command line: Enable-WSManCredSSP -Role client –DelegateComputer wsman/server name (repeat for each target BizTalk server)
- On each target BizTalk server execute the following from a Powershell command line:Enable-WSManCredSSP –Role server
- On the build server, update Group Policy to allow your credentials to be delegated to the remote server.
Open gpedit.msc and browse to Computer Configuration > Administrative Templates > System > Credentials Delegation.
Double-click "Allow delegating fresh credentials with NTLM-only Server Authentication".
Enable the setting and add the BizTalk servers to the server list as WSMAN/BizTalkServerName. (You can enable all servers by entering WSMAN/*.)
Download the Powershell Script
The Powershell Scripts can be downloaded at https://www.biztalkers.com/downloads/downloads.aspx
I’m afraid I can’t publish the xaml because it contains non-public information. However, hopefully there’s enough information in this blog post for you to adapt the standard TFS build definition
|Problem ||Resolution |
When running the TFS build you may receive errors reporting that the schema cs files used for unit test (eg modified_OP-Order-v1.xsd.cs) could not be found.
Ensure that the “MSBuild Platform” property within the “Process” tab of the build definition is set to “X86” (rather than the default value of “Auto”)
|TFS build complains that MSI missing || |
Ensure you’ve included the .btdfproj in the projects to build on the process tab
Problem with assemblies missing from MSI
Check you have added the TeamBuild property to the btdfproj file: <TeamBuild Condition=" '$(TeamBuild)' == '' ">False</TeamBuild>
Tom Abrahams (http://www.tfabraham.com/blog/) for his amazing effort in taking the BTDF to where it is today. All those who think Tom deserves a Connected Systems MVP – have a word with Microsoft!
Randy Aldrich Paulo (http://randypaulo.wordpress.com/2012/01/31/automating-silent-install-biztalk-deployment-framework-btdf-using-powershell/) for a great post that provided me with the basis for the development of my Powershell Scripts