Deploying with BTDF using Powershell

Deploying with BTDF using Powershell

General info

During one of my projects, I was asked to find a way to simplify the BizTalk deployment.
BizTalk Deployment Framework is a great tool, but it can be a lot of work if you have a large environment. First installing the MSI on each BizTalk server in the group, undeploy the BizTalk application(s), deploy the BizTalk application on the last server, etc.

In this situation Powershell can be a great way out, but where do you start?
At the ‘all-go-meeting’ just one requirement was set, the current way of deployment was not to be touched.

So I started to go through numerous blogs.


I’m not going into details about the BTDF, I assume most of you use it or at least you have heart of it.
Just  some remarks about the changes done to BTDF at the project:

  • build templates have been changed to store the msi on a shared drive: /, including the SettingsFileGenerator.xml
  • all relevant files are placed in the Deployment folder
  • the default name for the btdf project file, being Deployment.btdfproj.

BizTalk ALM

Short explanation

A less known project is the BizTalk ALM project. It is a great way of implementing ALM and BizTalk, we all know it is not that strait forward.
Following the project means changing the build templates and create a new build for each ‘group’ of applications you want to deploy, change the structure in TFS, etc. Not the thing we want.
It also doesn’t foresee in just an undeploy of applications.

Undeploying and deploying is based on the order of the BizTalk applications names in the text file. Undeploy is done in a reverse order, meaning the last application is undeployed first and deployed last.

To define the environment and when the deploy to BizTalk needs to happen, 2 system variables are needed.

  • BTDF_Env: the environment. The value depends on the notation used in the exported settings file from the BTDF.
  • BTDF_DeployToBizTalk: boolean to define if the deploy to BizTalk needs to run.

So I started playing around with the provided Powershell scripts.
I still use the system variables, but then ….

Where it all happens

The text file became a csv file, the Deploy.ps1 and install-BizTalkApplication.ps1 changed just a little and I created a new script file to determine if there are more than one BizTalk server in the environment and use Powershell Remote to deploy on the other servers.

Let me explain the files.


This comma separated file contains the applications to undeploy and/or deploy.

the structure:


  • Action: Undeploy/Deploy
    • Undeploy: will undeploy the application from BizTalk, but leaves the files on disk
    • Deploy: will install the new files, create the bindings (if there are any) and deploy the application to BizTalk depending on the system settings as mentioned previously.
  • ApplicationName: the application name.
  • Version:
    • Undeploy: the current version deployed
    • Deploy: the version to be deployed
  • MsiLocation: the location of the msi


The only thing this script does, is to get the list of BizTalk servers belonging to the same group and determine if the Deploy.ps1 script needs to run using Powershell Remote or not.
One thing to keep in mind, you need to run the script as a user that is a member of the BizTalk Administrators AD group. Otherwise non of the scripts will work.


Before doing any processing of the Applications.txt file, verify if the 2 required BTDF environment variables are present.

A watchful eye has seen the 2 imports at the top, the first I’ll tackle shortly. The second one is just a C# class, Invoke-MSBuild, to invoke MS Build.
If retrieving the system settings was successful, the ‘base’ of the installation folder is set and the text file is read.
Next the text file is read line per line, meaning that you are responsible for the correct order for undeploy and/or deploy.

If the action is Undeploy, the location of the .btdfproj and logfile are constructed together with the arguments for MS Build.
Everything is passed as MSArguments parameters to Invoke-MSBuild which returns the exit code.
Depending on the outcome, either all further processing is stopped or the next line is handled.

In case of a Deploy action, the parameters for the Install-BizTalkApplication function are gathered or created.


The function needs the following arguments:

  • MsiFile: the file name of the msi file to install.
  • FilesLocation: the location of the msi and settingsFileGenerator.xml
  • ApplicationInstallPath: the install location for the msi. The format is as follows: C:Program Files (x86)
  • Environment: the environment as defined in the system variable BTDF_Env, a test is included to ensure only the allowed values are used
  • BTDFProjectFile: the name of the BTDF project file. By default it contains the hard-coded value “Deployment.btdfproj”.
  • BTDeployMgmtDB: the boolean value from the system settings variable BTDF_DeployToBizTalk.
  • SkipUndeploy: hardcoded to true. Again included to provide more flexibility in the future.

Step 1 is to install the msi, this is done by constructing the necessary arguments and passing them to msiexec.exe.

When the exit code is different from 0, an output is written to the console and processing will be canceled.

Because there is a difference in arguments when the BizTalk application has bindings or not, I verify if the SettingsFileGenerator.xml file is present. When the file isn’t separately stored, a new column could be added to the txt file to indicate if the application contains bindings.

For applications containing bindings the first step will be to create the different BTDF export files.

This is done by, again, creating the arguments and passing them to the EnvironmentSettingsExporter.exe. (included in BTDF)

In case the SettingsFileGenerator.xml is on a different location, you need to change the first argument.

People who have work with BTDF may recognize the different arguments, for those who don’t recognize them more infomation can be found in the documentation of BTDF.

The next step is to create the arguments for the deployment to BizTalk.

The difference between the 2 blocks is just the envSettings variable which contains the location of the exported settings file corresponding to the environment.

For more information on the different arguments, please have a look at the documentation of BTDF.

Why all the separate scripts?

You may wander why all the separate scripts, well this allows you the run the scripts independent from each other.
In case Powershell Remote is not allowed or required, start from the Deploy.ps1 script. Otherwise start from OneClickDeploy.ps1. Want to just use the Install-BizTalkApplication function, well just call it from wherever you want and provide the necessary arguments.

Running it all

Powershell settings

Know how to run this all?
First make sure that the execution policy in Powershell is set to Unrestricted.

Set-ExecutionPolicy Unrestricted

If you want to use Powershell Remote, don’t forget to enabled it on all the servers within the BizTalk Group. Not all companies allow Powershelll Remote with an unrestricted policy.
Understandable, the server is remotely accessible and you can run any Powershell script you want. But as mentioned before, you can run the scripts on each server, which still saves you a lot of work.

Good to know

Keep in mind that all the Powershell scripts and the CSV file need to be in the same folder and that the user running the script has access to the location of the msi’s. Also that the user is a member of the BizTalk Administrators Group in AD.
And one final thing, the scripts need to be executed from a BizTalk server.

When everything is set up correctly, simply run Powershell (86) as Admin, navigate to the directory of the scripts and run the script you want.
Being OneClickDeploy.ps1 to use Powershell Remote for the other BizTalk servers or Deploy.ps1 to just run it on the server.

End word

I’m aware that there are different ways to achieve the same goal, this is just one way of doing it and I wanted to share it with my fellow BizTalk developers.
As mentioned at the start of this article, the starting point was the BizTalk ALM project. If you look at the Powershell scripts included in that project, there will be some similarities.