Geeks With Blogs

News This is the *old* blog. The new one is at
Elton Stoneman
This is the *old* blog. The new one is at


Often in BizTalk deployments you need to do additional work after installation. Typically your full install process may need to:

  • Install BizTalk artifact assemblies to the GAC
  • Install application dependencies to the GAC
  • Register an application source name in the registry, for logging to the Event Log
  • Create FILE send or receive locations on the local filesystem
  • Add application store configuration settings to Enterprise Single Sign-On (SSO)
  • Add log4net configuration settings to BTSNTSvc.exe.config

You can achieve this with a single BizTalk installer by configuring resources and post-processing scripts, and exporting an MSI from the application. Various scripting languages are supported in BizTalk installations (batch files, VBScript etc.), except the most logical – PowerShell, which gives first-class support for the filesystem, the registry, XML files and .NET objects. You can still use PowerShell by including scripts as resources, and using a batch file as the post-processing script, which acts as a harness to call the PowerShell scripts.

This walkthrough addresses all the points above. The completed BizTalk application is on MSDN Code Gallery here: BizTalk PowerShell Deployment Sample – import and install the MSI to deploy with the PowerShell script, or browse the ZIP file to see the scripts and resources.

1. Install BizTalk artifact assemblies to the GAC

This is straightforward, set the resource option "Add to the global assembly cache on MSI file install" to true – this happens by default if you add a BizTalk Assembly resource in the Administration Console:

Using the command line though, this is not the default option so you need to explicitly set –Options:GacOnInstall in BTSTask:

btstask AddResource







2. Install application dependencies to the GAC

As 1), except the resource type is System.BizTalk:Assembly (in BTSTask you can omit "System.BizTalk"). The command requires the same flag to add to the GAC on install:

btstask AddResource








In this case, I'm installing the SSOConfig assembly (from SSO Config Tool) which provides static .NET classes for accessing the SSO application configuration store. The Overwrite flag is set in case the resource already exists in another application.

3. Register an application source name in the registry, for logging to the Event Log

To log to the Application event log with your own source name, you need to add a registry key with the app name, and the name of the handler:


In PowerShell, this is done in using the New-Item cmdlet to create the key, and New-ItemProperty to set the key value:

New-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Eventlog\Application\PowerShellSample' -Force

New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Eventlog\Application\PowerShellSample' -Name 'EventMessageFile' -PropertyType ExpandString -Value 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\EventLogMessages.dll' –Force


(HKLM: is a PowerShell drive mapped to HKEY_LOCAL_MACHINE, and the –Force flag overwrites existing values).

To execute the PowerShell script on install, we need a batch file which BizTalk can run as a post-processing script. The batch file is very simple, just separating install and uninstall logic to individual PowerShell scripts, and redirecting script output to a log file:

cd "%BTAD_InstallDir%\Deployment"

if "%BTAD_InstallMode%" == "Install" ( powershell ".\PowerShellSample.Install.ps1" >> PowerShellSample.Install.ps1.log )

if "%BTAD_InstallMode%" == "Uninstall" ( powershell ".\ PowerShellSample.Uninstall.ps1" >> PowerShellSample.Uninstall.ps1.log )


Both the CMD and PS1 files need to be added as resources to the BizTalk application. The PS1 files are of type BizTalk:File, and the CMD harness is of type BizTalk:PostProcessingScript:


btstask AddResource






btstask AddResource






4. Create FILE send or receive locations on the local filesystem

If you need to create static file locations, the same New-Item cmdlet is used with the filesystem provider. Specify the full path for the directory and any intermediate directories will be created if they don't exist. Use the –Force flag to suppress warnings if the directory already exists:

New-Item –Path 'c:\receiveLocations\x\y\z' -ItemType Directory –Force

Note that the resources in the BizTalk application are copies rather than references, so if you modify your PS1 files, you'll need to update the resource (in the Administration Console, select the resource and use Modify... Refresh, or re-run the BTSTask command).

5. Add settings to Enterprise Single Sign-On (SSO)

If you're using SSO to store group-wide application config, you can create or export an XML file of the settings using SSO Config Tool. We add the .ssoconfig file as a File resource to the application, then in the install script use PowerShell to call a .NET method to import the settings using the SSOConfig.SSOApplication class. The SSOConfig assembly is a resource which has already been deployed to the GAC by this point in the installation:

[Reflection.Assembly]::Load('SSOConfig, Version=, Culture=neutral, PublicKeyToken=656a499478affdaf')

$configPath = [IO.Path]::Combine($env:BTAD_InstallDir, 'Deployment\PowerShellSample.ssoconfig')

$app = [SSOConfig.SSOApplication]::LoadFromXml($configPath)



Note that the PowerShell script has access to all the environment variables set by BizTalk on the install – accessed by prefixing $env: to the variable name, as we do here to get the installation directory from the installer ($env:BTAD_InstallDir).

6. Add settings to BTSNTSvc.exe.config

Modifying XML is straightforward in PowerShell. We want to configure an Event Log appender in the BizTalk service config file by adding the following XML:


<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net, Version=, Culture=neutral, PublicKeyToken=1b44e1d426115821" />




<appender name="Sixeyed.CacheAdapter.EventLogAppender" type="log4net.Appender.EventLogAppender, log4net, Version=, Culture=neutral, PublicKeyToken=1b44e1d426115821">

<param name="LogName" value="Application"/>

<param name="ApplicationName" value="Sixeyed.CacheAdapter"/>

<layout type="log4net.Layout.PatternLayout">

<conversionPattern value="%date [%thread] %logger %level - %message%newline" />




<logger name="Sixeyed.CacheAdapter.Log">

<level value="WARN" />

<appender-ref ref="Sixeyed.CacheAdapter.EventLogAppender" />




The Get-ItemProperty cmdlet can read the BizTalk install path from the registry, then Get-Content reads the file – casting it to XML for subsequent processing:

$installPath = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\BizTalk Server\3.0' -Name 'InstallPath'

$btsConfigPath = [IO.Path]::Combine($installPath.InstallPath, 'BTSNTSvc.exe.config')

$xml = [xml] (Get-Content $btsConfigPath)


On a fresh install, the config file is quite bare and doesn't include a <configSections> element, so in that case we need to add both <configSections> and <log4net> nodes. We can't guarantee that other solutions haven't already modified the config file though, so <configSections> may exist, and <log4net> may also exist – in which case, we just need to add our specific appender and logger values (log4net allows you to define multiples of these in config, and we specify names which we can expect to be unique).

To achieve this, the script checks for each element first, creates it if it doesn't exist, then adds the specific settings:

$configSections = $xml.SelectSingleNode('configuration/configSections')

if ($configSections -eq $null)


    $configSections = $xml.CreateElement('configSections')

    $firstChild = $xml.configuration.get_FirstChild()

    $xml.configuration.InsertBefore($configSections, $firstChild)



$log4netSection = $configSections.SelectSingleNode('section[@name="log4net"]')

if ($log4netSection -eq $null)


    $log4netSection = $xml.CreateElement('section')

    $log4netSection.SetAttribute('name', 'log4net')

    $log4netSection.SetAttribute('type', 'log4net.Config.Log4NetConfigurationSectionHandler, log4net, Version=, Culture=neutral, PublicKeyToken=1b44e1d426115821')    

    $configSections.AppendChild($log4netSection )




Finally the updates are saved over the original file:





The main limitation with any post-processing script, is that the target environment selected for the install is not available. If you have multiple bindings files, the environment selected at runtime is only alive for the duration of the MSI import – the install has no reference to it, and there's no record made in the management database (not that I can see, please correct me if there is). This means you can't switch your script based on environment (e.g. to use different SSO config settings for System Test and Production). If that's a serious restriction you may prefer to create different MSIs per-environment in your build process, each containing the correct bindings file and scripts.

Specific to this approach, you need to have PowerShell installed on all the target machines, and configured to allow script execution (by default, scripts are not permitted to execute, as a security measure). Hopefully this is becoming the norm. Security also needs to be considered – the sample app writes to the registry and to SSO, so the installing context needs to have explicit permissions. The BizTalk installer runs under a separate security context from the installing user (by a trial-and-error process, this is NT AUTHORITY\ANONOYMOUS LOGON in my Server 2003 VM), so if you're amending SSO you'll need to set your SSO Administrators group membership correctly.


The completed PowerShell scripts should be straightforward to read and maintain. All the post-installation requirements are implemented using a single technology, and many of the functions are reusable and could easily be parameterised and moved to a central script. The script is easy to test outside of the installer runtime, either manually using a batch file as a test harness (which sets up the relevant environment variables and then calls the post-processing file), or worked into an automated unit test.

The approach is not limited to BizTalk installations, so similar tasks for .NET deployments which are currently done with custom assemblies or Wix script can be isolated in the same way. With BizTalk and .NET installs using the same technology, you'll build up a library of high-quality, reusable PowerShell scripts.

I also like having the scripts deployed as part of the install, so in combination with the log files, you can see exactly what's been done to your environment and modify if necessary.


With native cmdlets and community scripts, together with WMI, XML and .NET code, you can achieve any desired functionality with PowerShell scripts, and have them rapidly developed and tested. So you can easily add code to update version numbers in config files, remove your assemblies from the GAC on uninstall, access performance counters etc. And PowerShell scripts are just plain text so you can extract them into a T4 template and generate different scripts for different environments in your build process.

Posted on Monday, June 8, 2009 3:58 PM BizTalk 2006 R2 , Code Gallery , BizTalk 2009 | Back to top

Comments on this post: Using PowerShell in BizTalk Post-Processing Scripts

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Excellent article on improving Biztalk deployment using PowerShell. Also , I am a bit curious to know about your impression on the VSTS 2008 integration and MSBuild features available with Biztalk 2009 and I wish to see, if there is some article enlists pros and cons using different deployment options available, like DOS batch file, PowerShell, MSBuild, NAnt etc.
Left by Rajesh on Jun 12, 2009 9:48 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Thanks Rajesh, glad you found it useful. Stephen W Thomas has a great post about integrating BTS 2009 with MSBuild here: - which includes setting up a TFS build.

Those deployment options are all viable and can be made to achieve the same things, the issue is what your deployment experience will be like, and what dependencies you can tolerate on your servers. If you're happy to use MSBuild/NAnt with a batch file to do deployments, you'll be able to reuse all your build scripts, but it's not a great experience to hand over to a support team.

My preference for this is that all you handover for deployment is an MSI. PowerShell is becoming increasingly popular, and it's a nice bridge between support guys who like scripts, and dev guys who like code, so both teams can track down issues in deployment. It's also powerful in lots of different scenarios, and I like the idea of having a simplified dev toolset - PowerShell lets you do a lot in script that would otherwise require custom assemblies.
Left by Elton on Jun 12, 2009 3:46 PM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Interesting post and thanks for sharing.I like the way you describe all the things in this post.Some great information to be absorbed in this post.will be referring a lot of friends about this.Keep it up.
Left by uterine fibroid embolization on Apr 12, 2010 9:11 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Hi, this is one of the best site for the readers and the tips are really very innovative one.Some great information to be absorbed in this post. Thanks for sharing.Keep posting.
Left by dedicated web hosting-54 on Apr 22, 2010 9:38 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
I wanna say thank you for the information you have shared. Just continue writing this kind of post. I will be your loyal reader. Thanks again. Interesting post and thanks for sharing.
Left by Judaism History on May 29, 2010 5:35 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
This was a very well-written and enjoyable post to read.I like the way you describe all the things and the examples.Thanks a lot for sharing.Keep up the good works.
Left by Dormire a Lucca on Jun 08, 2010 4:27 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
This post was very nicely written, and it also contains a lot of useful facts. Thanks a lot for sharing.Keep blogging.
Left by weight-loss46 on Jun 14, 2010 7:10 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
really very useful information... thank you... I like your site. porno izle
Left by yasal200 on Oct 06, 2010 7:25 PM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
This is my first time i visit here. I have been reading a lot on here and have picked up some great ideas.I don't know what to say except that I have enjoyed reading.Thanks a lot.Keep blogging.
Left by get motivated seminars on Oct 08, 2010 9:47 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Thank you for sharing
Left by kapadokya on Nov 03, 2010 6:53 PM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Regarding the creation of FILE send and receive locations on the local file system, it could be nice if the script could enumerate all the configured receive locations and send ports, retrieve the file paths and automatically create the appropriate folders in the local file system. This would avoid hardcoding file paths in the script.
To do this, the script could take as input a binding file and for each configured file location configured, create the required folders and subfolders in the local file system.

Another solution could be to access the "adm_ReceiveLocation" and "bts_sendport_transport" tables found in the BizTalk management database to create the appropriate file locations.

Left by Sh@h on Nov 12, 2010 4:16 PM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Here is a post for a similar concept for #5: I base the creation of the ports off a bindings file. Thanks
Left by Ben Cline on Feb 15, 2011 11:34 PM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Incredible article, it makes a change when you find someone contributing to the net. We are an entertaining group In London that are willing to travel to you anywhere in the world! :-) Indian escorts London
Left by London Escorts on Jun 05, 2011 12:29 AM

# re: Using PowerShell in BizTalk Post-Processing Scripts
Requesting Gravatar...
Really a superb entry. I am very impressed with the article I have just read. Would be waiting for more stuff from yourside.
Left by forex trading on Jun 27, 2011 7:49 AM

Your comment:
 (will show your gravatar)

Copyright © Elton Stoneman | Powered by: