Powershell Script Deployment for BizTalk Server Projects
Introduction
BizTalk Server offers many ways to deploy the code into a runnable application. However, in order to master what is included in the deployment, we have the solution to either deploy every time the full application using the MSi, or deploy only modifications that could include a single DLL or update a specific port.
Although MSI files are very useful, they have major drawbacks that: You don't know what you are deploying! and the MSI you are deploying depends a lot on how the MSI was generated and what were the options checked / unchecked (GAC on install? GAC on import? choose the DLLs that were exported, etc.)
Deploying using Cmdlet PowerShell
In order to master the deployment like upgrading a single DLL, or a bunch of DLLs, with a specific order, on different BizTalk Server Applications, in a Single “Double Click” then PowerShell might be the solution
There are many advantages of using PowerShell, among which:
- combine different types of deployment capabilities (WMI, btstask, bttdeploy, other executable...)
- create CmdLets or functions to do specific tasks
- master the deployment: using scripting we know exactly what we are deploying, upgrading and doing
- add logs to the deployment, very useful when we have a dedicated team that does the deployment
Basic CmdLets functions
CmdLets that are basic are typically the version of the framework you are deploying, application you are trying to deploy.
The nice thing about PowerShell is that it can read XML, so configuration files are useful in order to keep the same deployment script
function Display-Info
{
param([string]$ApplicationName=$(Throw 'ApplicationName is required'), [string]$Environment=$(Throw 'Environement is Required'))
Write-Output "************* DEPLOYMENT INFORMATION ************* "
Write-Output "Application : $ApplicationName"
Write-Output "ServerName : $env:computername"
Write-Output "Environement According to Config : $Environment"
Write-Output "************* DEPLOYMENT INFORMATION ************* "
}
function Get-EnvFromConfig
{
$xml = [xml](get-content .\Scripts\BtsDeploy.config)
$ServerName = $env:computername;
$MatchedServer = $xml.Configuration.Environments.Server | Where-Object {$_.Name -eq "$ServerName"}
if($MatchedServer -eq $null)
{
$Environment = "DEV";
}
else
{
$Environment = $MatchedServer.GetAttribute("Environment");
}
return $Environment;
}
BizTalk Exe CmdLets functions
Below is an example of how to call btstask inside PowerShell script. The below example shows how to add an application, the code checks if the application to be added exists or not, before calling the btstask:
function Add-Application
{
param([string]$ApplicationName=$(Throw 'ApplicationName is required'))
$btsApplicationList = btstask ListApps
$AppNameToTest = '"' + $ApplicationName + '" -Description'
if($btsApplicationList -match $AppNameToTest)
{
Write-Output "Application $ApplicationName already exists !"
}
else
{
btstask AddApp -ApplicationName:$ApplicationName
}
}
WMI CmdLets functions
Using the WMI objects for BizTalk Server is interesting. It avoids using the administrative console, and therefore avoids clicking too many times. WMI is a robust way to do many things, below is the code using WMI to Start a Send Port:
function Start-SendPort($SendPortName)
{
Write-Output “Starting SendPort $SendPortName”
$varSendPort = Get-WmiObject -class MSBTS_SendPort -computername $computer -namespace $namespace | Where-Object{$_.Name -eq "$SendPortName"}
[void]$varSendPort.Start()
if($?)
{
Write-Output “$SendPortName Started Successfully”
}
else
{
$host.ui.RawUI.ForegroundColor = "Red"
Write-Output $error[0]
Write-Output “Error : $SendPortName Start Failed”
$host.ui.RawUI.ForegroundColor = $ColorOrigin
}
}
ExplorerOM CmdLets
There are few things that cannot be done using standard btstask or WMI objects, so in this case we could use the ExplorerOM object. Below is the code that adds a reference application:
function Add-ReferenceApplication
{
param([string]$ApplicationName=$(Throw 'ApplicationName is required'), [string]$ReferencedApplicationName=$(Throw 'ReferencedApplicationName is required'))
Write-Output "************* Start Adding Application Reference: App : $ApplicationName, Ref : $ReferencedApplicationName************* "
$BtsConnectionString = Get-BtsConnectionString
Write-Output "$BtsConnectionString"
[void] [System.reflection.Assembly]::LoadWithPartialName("Microsoft.BizTalk.ExplorerOM")
$Catalog = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
$Catalog.ConnectionString = $BtsConnectionString + ";Integrated Security=SSPI"
$AppNameRefFrom = $Catalog.Applications["$ApplicationName"]
$AppNameRefTo = $Catalog.Applications["$ReferencedApplicationName"]
$AppNameRefFrom.AddReference([Microsoft.BizTalk.ExplorerOM.Application] $AppNameRefTo)
# Save the changes
$Catalog.SaveChanges();
if(!$?)
{
$host.ui.RawUI.ForegroundColor = "Red"
Write-Output $error[0]
$host.ui.RawUI.ForegroundColor = $ColorOrigin
}
Write-Output "************* End Adding Application Reference: App : $ApplicationName, Ref : $ReferencedApplicationName************* "
}
Conclusion
In time you can come to a very nice BizTalk Deployment Framework, using a single line of code someone could deploy an assembly, or import bindings, or add a referenced application, or whatever other operation.
We are using this deployment framework, it handles may be 95% of all BizTalk Operations, there are many features that we use like logging, backing up before deploying, restarting the hosts, etc.
The 5% that we do not do, are related to the complexity or these are things that we do on a one-shot basis (terminate all running instances of an application). Even though it is simple to implement, sometimes it is better not to, as the script could inadvertently terminate important running instances. Where we still need human intelligence we do not script.
The powerful feature here is a customization.
See Also
Another important place to find a huge amount of BizTalk related articles is the TechNet Wiki itself. The best entry point is BizTalk Server Resources on the TechNet Wiki.