<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>BizTalk 2006 R2</title>
        <link>http://geekswithblogs.net/EltonStoneman/category/7948.aspx</link>
        <description>BizTalk 2006 R2</description>
        <language>en-GB</language>
        <copyright>EltonStoneman</copyright>
        <managingEditor>elton.stoneman@gmail.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>Using PowerShell in BizTalk Post-Processing Scripts</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/06/08/using-powershell-in-biztalk-post-processing-scripts.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Often in BizTalk deployments you need to do additional work after installation. Typically your full install process may need to: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Install BizTalk artifact assemblies to the GAC &lt;/li&gt;
    &lt;li&gt;Install application dependencies to the GAC &lt;/li&gt;
    &lt;li&gt;Register an application source name in the registry, for logging to the Event Log &lt;/li&gt;
    &lt;li&gt;Create FILE send or receive locations on the local filesystem &lt;/li&gt;
    &lt;li&gt;Add application store configuration settings to Enterprise Single Sign-On (SSO) &lt;/li&gt;
    &lt;li&gt;Add log4net configuration settings to BTSNTSvc.exe.config &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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. &lt;/p&gt;
&lt;p&gt;This walkthrough addresses all the points above. The completed BizTalk application is on MSDN Code Gallery here: &lt;a href="http://code.msdn.microsoft.com/BTSPowerShellSample"&gt;BizTalk PowerShell Deployment Sample&lt;/a&gt; – import and install the MSI to deploy with the PowerShell script, or browse the ZIP file to see the scripts and resources. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;1. Install BizTalk artifact assemblies to the GAC &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;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: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/060809_2059_UsingPowerS1.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;Using the command line though, this is not the default option so you need to explicitly set –Options:GacOnInstall in BTSTask: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;btstask AddResource&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-ApplicationName:PowerShellSample  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Type:BizTalkAssembly  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Options:GacOnInstall  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Source:PowerShellSample.Schemas.dll  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Destination:%BTAD_InstallDir%\PowerShellSample.Schemas.dll &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;2. Install application dependencies to the GAC &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;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: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;btstask AddResource  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-ApplicationName:PowerShellSample  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Type:Assembly  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Options:GacOnInstall  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Overwrite  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Source:.\Dependencies\SSOConfig.dll  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Destination:%BTAD_InstallDir%\Dependencies\SSOConfig.dll &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;In this case, I'm installing the SSOConfig assembly (from &lt;a href="http://ssoconfigtool.codeplex.com/"&gt;SSO Config Tool&lt;/a&gt;) 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. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;3. Register an application source name in the registry, for logging to the Event Log &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;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: &lt;/p&gt;
&lt;p&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\PowerShell.Sample &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/060809_2059_UsingPowerS2.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;In PowerShell, this is done in using the &lt;strong&gt;New-Item&lt;/strong&gt; cmdlet to create the key, and &lt;strong&gt;New-ItemProperty&lt;/strong&gt; to set the key value: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;New-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Eventlog\Application\PowerShellSample' -Force &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;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 &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;(HKLM: is a PowerShell drive mapped to HKEY_LOCAL_MACHINE, and the –Force flag overwrites existing values). &lt;/p&gt;
&lt;p&gt;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: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;cd "%BTAD_InstallDir%\Deployment" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;if "%BTAD_InstallMode%" == "Install" ( powershell ".\PowerShellSample.Install.ps1" &amp;gt;&amp;gt; PowerShellSample.Install.ps1.log ) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;if "%BTAD_InstallMode%" == "Uninstall" ( powershell ".\ PowerShellSample.Uninstall.ps1" &amp;gt;&amp;gt; PowerShellSample.Uninstall.ps1.log ) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;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: &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;btstask AddResource  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-ApplicationName:PowerShellSample  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Type:File  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Source:.\Deployment\PowerShellSample.Install.ps1  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Destination:%BTAD_InstallDir%\Deployment\PowerShellSample.Install.ps1 &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;btstask AddResource  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-ApplicationName:PowerShellSample  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Type:PostProcessingScript  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Source:.\Deployment\PowerShellSample.PostProcessing.cmd  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;-Destination:%BTAD_InstallDir%\Deployment\PowerShellSample.PostProcessing.cmd &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;4. Create FILE send or receive locations on the local filesystem &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you need to create static file locations, the same &lt;strong&gt;New-Item&lt;/strong&gt; 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: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;New-Item –Path 'c:\receiveLocations\x\y\z' -ItemType Directory –Force &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;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 &lt;em&gt;Modify... Refresh&lt;/em&gt;, or re-run the BTSTask command). &lt;/p&gt;
&lt;p&gt;&lt;em&gt;5. Add settings to Enterprise Single Sign-On (SSO) &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you're using SSO to store group-wide application config, you can create or export an XML file of the settings using &lt;a href="http://ssoconfigtool.codeplex.com/"&gt;SSO Config Tool&lt;/a&gt;. 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: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;[Reflection.Assembly]::Load('SSOConfig, Version=1.1.0.0, Culture=neutral, PublicKeyToken=656a499478affdaf') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$configPath = [IO.Path]::Combine($env:BTAD_InstallDir, 'Deployment\PowerShellSample.ssoconfig') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$app = [SSOConfig.SSOApplication]::LoadFromXml($configPath) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$app.SaveToSSO() &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;Note that the PowerShell script has access to all the &lt;a href="http://msdn.microsoft.com/en-us/library/aa559790.aspx"&gt;environment variables set by BizTalk&lt;/a&gt; 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). &lt;/p&gt;
&lt;p&gt;&lt;em&gt;6. Add settings to BTSNTSvc.exe.config &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;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: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;  &amp;lt;configSections&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    &amp;lt;section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821" /&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;  &amp;lt;/configSections&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;  &amp;lt;log4net&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    &amp;lt;appender name="Sixeyed.CacheAdapter.EventLogAppender" type="log4net.Appender.EventLogAppender, log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821"&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;      &amp;lt;param name="LogName" value="Application"/&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;      &amp;lt;param name="ApplicationName" value="Sixeyed.CacheAdapter"/&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;      &amp;lt;layout type="log4net.Layout.PatternLayout"&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        &amp;lt;conversionPattern value="%date [%thread] %logger %level - %message%newline" /&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;      &amp;lt;/layout&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    &amp;lt;/appender&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    &amp;lt;logger name="Sixeyed.CacheAdapter.Log"&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;      &amp;lt;level value="WARN" /&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;        &amp;lt;appender-ref ref="Sixeyed.CacheAdapter.EventLogAppender" /&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;      &amp;lt;/logger&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;  &amp;lt;/log4net&amp;gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Get-ItemProperty&lt;/strong&gt; cmdlet can read the BizTalk install path from the registry, then &lt;strong&gt;Get-Content&lt;/strong&gt; reads the file – casting it to XML for subsequent processing: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$installPath = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\BizTalk Server\3.0' -Name 'InstallPath' &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$btsConfigPath = [IO.Path]::Combine($installPath.InstallPath, 'BTSNTSvc.exe.config') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$xml = [xml] (Get-Content $btsConfigPath) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;On a fresh install, the config file is quite bare and doesn't include a &amp;lt;configSections&amp;gt; element, so in that case we need to add both &amp;lt;configSections&amp;gt; and &amp;lt;log4net&amp;gt; nodes. We can't guarantee that other solutions haven't already modified the config file though, so &amp;lt;configSections&amp;gt; may exist, and &amp;lt;log4net&amp;gt; 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).  &lt;/p&gt;
&lt;p&gt;To achieve this, the script checks for each element first, creates it if it doesn't exist, then adds the specific settings: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$configSections = $xml.SelectSingleNode('configuration/configSections') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;if ($configSections -eq $null)  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;{ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    $configSections = $xml.CreateElement('configSections') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    $firstChild = $xml.configuration.get_FirstChild() &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    $xml.configuration.InsertBefore($configSections, $firstChild) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$log4netSection = $configSections.SelectSingleNode('section[@name="log4net"]') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;if ($log4netSection -eq $null) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;{ &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    $log4netSection = $xml.CreateElement('section') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    $log4netSection.SetAttribute('name', 'log4net') &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    $log4netSection.SetAttribute('type', 'log4net.Config.Log4NetConfigurationSectionHandler, log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821')     &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;    $configSections.AppendChild($log4netSection ) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;... &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;Finally the updates are saved over the original file: &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;$xml.Save($btsConfigPath) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Limitations &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;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. &lt;/p&gt;
&lt;p&gt;Specific to this approach, you need to have PowerShell installed on all the target machines, and configured to allow script execution (by default, &lt;a href="http://www.windowsecurity.com/articles/PowerShell-Security.html"&gt;scripts are not permitted to execute&lt;/a&gt;, 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 &lt;strong&gt;NT AUTHORITY\ANONOYMOUS LOGON&lt;/strong&gt; in my Server 2003 VM), so if you're amending SSO you'll need to set your SSO Administrators group membership correctly. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Benefits &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;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. &lt;/p&gt;
&lt;p&gt;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.  &lt;/p&gt;
&lt;p&gt;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. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Extensions &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;With native cmdlets and &lt;a href="http://poshcode.org/"&gt;community scripts&lt;/a&gt;, 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, &lt;a href="http://weblogs.asp.net/adweigert/archive/2008/10/31/powershell-install-gac-gacutil-for-powershell.aspx"&gt;remove your assemblies from the GAC&lt;/a&gt; on uninstall, &lt;a href="http://www.leeholmes.com/blog/AccessingPerformanceCountersInPowerShell.aspx"&gt;access performance counters&lt;/a&gt; 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. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132694"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132694" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/132694.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/06/08/using-powershell-in-biztalk-post-processing-scripts.aspx</guid>
            <pubDate>Mon, 08 Jun 2009 20:58:18 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/132694.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/06/08/using-powershell-in-biztalk-post-processing-scripts.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/132694.aspx</wfw:commentRss>
        </item>
        <item>
            <title>BizTalk Cache Adapter Samples</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx</link>
            <description>&lt;p style="TEXT-ALIGN: center"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The sample BizTalk application provided with the &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx"&gt;BizTalk Cache Adapter&lt;/a&gt; on &lt;a href="http://biztalkcacheadapter.codeplex.com/"&gt;CodePlex&lt;/a&gt; illustrates three approaches for using the cache: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Simple Messaging – routes all messages configured for caching to the cache adapter, and sends cache-misses on to the service provider; &lt;/li&gt;
    &lt;li&gt;Orchestration – explicitly routes messages to either the cache adapter or service provider in orchestration logic; &lt;/li&gt;
    &lt;li&gt;Complex Messaging – routes messages configured for caching either to the cache adapter or to the service provider. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All the samples use FILE locations for the originating request and ultimate response. The expected locations will be created in the install, with sample request files in the receive locations. Enable the relevant receive location to run the sample, then copy the request file to the receive location again to re-run it – from the second run onwards, the responses should be the cached versions. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Installation&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;To use the samples, you'll need to install and configure a cache provider, the cache adapter, cache adapter sample, sample service, and the cache viewer (if you want to see the contents of the cache). &lt;/p&gt;
&lt;p&gt;Both the Cache Adapter and Sample BizTalk MSIs use PowerShell scripts for their post-processing steps. If you want to install from the MSIs, you'll need to have PowerShell installed and set up to enable script execution (&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;Set-ExecutionPolicy RemoteSigned&lt;/span&gt; is fine). &lt;/p&gt;
&lt;p&gt;1. Cache Provider. &lt;/p&gt;
&lt;p&gt;Download and install &lt;a href="http://www.alachisoft.com/ncache/ncache_express.html"&gt;NCache Express&lt;/a&gt; (this is a free edition, you'll have a product key emailed to you), and configure a cache instance for the samples by modifying the configuration file (config.ncconf – by default in C:\Program Files\NCache Express\config): &lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cache-config&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;name&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;Sixeyed.CacheAdapter.NCacheExpressProvider.Tests&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;inproc&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cleanup&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;interval&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;1sec&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;log&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;trace-errors&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;trace-debug&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;enabled&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;storage&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;cache-size&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;5mb&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;eviction-policy&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;default-priority&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;normal&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;eviction-ratio&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;10%&lt;/span&gt;"&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;eviction-enabled&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;perf-counters&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;enabled&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;false&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;/&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cache-config&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;configuration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;
&lt;p&gt;This creates a single-node cache on the local machine, limited to 5Mb of system memory. Start the cache by running the startcache tool (C:\Program Files\NCache Express\bin\tools): &lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;startcache Sixeyed.CacheAdapter.NCacheExpressProvider.Tests &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;- and verify it's there with listcaches. You should see the cache listed as Running: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach1.png" /&gt; &lt;/p&gt;
&lt;p&gt;2. Cache Adapter. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapter.msi is the BizTalk MSI which installs the adapter and artifacts. Import the application into BizTalk and run the installer. Verify the Sixeyed.CacheAdapter application is listed, and add the adapter in the Administration Console through &lt;em&gt;Platform Settings...Adapters...New&lt;/em&gt;. &lt;/p&gt;
&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;em&gt;Note: the installer adds the necessary adapter files to the GAC and sets up the registry keys. If you don't use the MSI, manual installation steps are: add the files from the Binaries release to a local directory and to the GAC; modify run the .REG command to specify assembly paths and import the .REG file; add the BizTalk artifact resources to your own application. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;2. Cache Adapter Sample. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapterSample.msi is the BizTalk MSI which installs the sample application and artifacts, and configures the ports. Import the application into BizTalk and run the installer. Verify the Sixeyed.CacheAdapterSample application is listed, and that the message types are configured in SSO (check the contents of SSO application &lt;strong&gt;Sixeyed.CacheAdapter&lt;/strong&gt;). &lt;/p&gt;
&lt;p style="MARGIN-LEFT: 36pt"&gt;&lt;em&gt;Note: the installer creates FILE send and receive locations, copies sample messages, and sets up SSO configuration for the cached message types. If you don't use the MSI, manual installation should follow the steps in: Source\Sixeyed.CacheAdapterSample\Deployment\Sixeyed.CacheAdapterSample.Install.ps1. &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;4. Sample Service. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapterSample.Service.msi installs a WCF service for the samples to call. Verify the service has deployed correctly by navigating to &lt;a href="http://localhost/Sixeyed.CacheAdapterSample/SampleService.svc?wsdl"&gt;http://localhost/Sixeyed.CacheAdapterSample/SampleService.svc?wsdl&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;5. Cache Viewer. &lt;/p&gt;
&lt;p&gt;Sixeyed.CacheAdapter.CacheViewer.msi installs a Winforms app for viewing cache contents. Run the application and configure it to use the running cache instance, by navigating to the NCacheExpressProvider assembly and selecting the NCacheExpressProvider: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach2.png" /&gt; &lt;/p&gt;
&lt;p&gt;- and specifying the ID of the cache instance: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach3.png" /&gt; &lt;/p&gt;
&lt;p&gt;(This is the same management UI used for configuring cache adapter ports in the BizTalk Administration Console. For the samples the Cache Id is &lt;strong&gt;Sixeyed.CacheAdapter.NCacheExpressProvider.Tests&lt;/strong&gt;). &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Simple Messaging&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;Enable the receive location &lt;strong&gt;ReceiveRequest_SimpleMessaging.FILE&lt;/strong&gt; and you should see the following workflow: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Message is picked up by the receive location, which is using the CacheXMLReceive pipeline. This checks the cache configuration in SSO, where the message type is configured for caching, so context property &lt;em&gt;IsMessageCacheEnabled&lt;/em&gt; is set to true; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_GetCache picks up the message and sends it to the cache adapter, using the request message to build a cache key, and checking for a response existing in the cache. There is no cached response, so the message returned from the cache adapter is the original request message, with context property &lt;em&gt;IsCached&lt;/em&gt; set to false; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_SendServiceRequest picks up the message and sends it to the service; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_PutCache picks up the service response and adds it to the cache, using the cache key from the original request; &lt;/li&gt;
    &lt;li&gt;Send port SimpleMessaging_SendServiceResponse picks up the service response and copies it to the output directory. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Check the cache viewer and you will see a byte array cached with a GUID key: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach4.png" /&gt; &lt;/p&gt;
&lt;p&gt;The GUID is the hash of the request message, and the byte array is the response message. Subsequent drops of the same request into the Requests folder will find the cached response at step 2, and the response will be the cached message. &lt;/p&gt;
&lt;p&gt;This workflow is suitable for any simple messaging solution, where static ports are used and where the original request and ultimate response can be auctioned by different ports. Configuration of the cache instance is contained in the send ports. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Orchestration &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The orchestration sample follows the same workflow as the Simple Messaging sample, and uses the same CacheXMLReceive pipeline to add the caching properties to the incoming message. The orchestration sample makes the cache access with explicit send and receives, and configuration of the cache instance is still contained in the send ports. &lt;/p&gt;
&lt;p&gt;Enable the receive location ReceiveRequest_Orchestration.FILE to run the sample. This is suitable for solutions where finer grained control is needed over the caching mechanism, and an orchestration is a viable option. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Complex Messaging &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Both the simple implementations use the cache adapter as a passthrough when there is no matching response in the cache – the incoming message is returned by the cache adapter, and a send port picks it up and routes it on the service. This is not suitable for more complex solutions: &lt;/p&gt;
&lt;ul style="MARGIN-LEFT: 37pt"&gt;
    &lt;li&gt;where the service is invoked through a dynamic port, as the outbound transport and location set on the original message are not reset by the cache adapter on the passed-through message; &lt;/li&gt;
    &lt;li&gt;where the originating receive is from a request-response port, as the interchange will accept the passed-through message as a response, and not return the actual service request. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these scenarios, the cache checking can be moved forward into the originating receive, so the cache adapter is only called if the response is known to exist in the cache. Added complexity here is that the receive pipeline needs to have the cache instance configuration, along with the send ports. This is shown in the Complex Messaging sample – run by enabling the receive location ReceiveRequest_ComplexMessaging.FILE: &lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;
    &lt;div&gt;Message is picked up by the receive location, which is using a custom pipeline – CheckCacheReceive. This consists of the SetMessageCacheProperties component which checks SSO to see if the message type is configured for caching, followed by the CheckIsCached component which checks is the message response is actually in the cache, and sets the &lt;em&gt;IsCached&lt;/em&gt; property: &lt;/div&gt;
    &lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2111_BizTalkCach5.png" /&gt; &lt;/p&gt;
    &lt;p style="MARGIN-LEFT: 18pt"&gt;Note that the cache instance is configured in the pipeline. Using a custom pipeline means you can configure the instance using the Cache Adapter UI in Visual Studio, which is easier and applies validation. While you could use a generic pipeline and modify the configuration per-instance on receive locations, that means manually hacking the XML; &lt;/p&gt;
    &lt;ol&gt;
        &lt;li&gt;If the message response is cached, send port ComplexMessaging_GetCache picks up the message and sends it to the cache adapter. The adapter is configured in the same way as other samples, and uses the same logic – but in this case the response is known to be cached, so it will be returned and the request message should never be passed-through; &lt;/li&gt;
        &lt;li&gt;If the message response is not cached, send port ComplexMessaging_SendServiceRequest calls the service provider passing the original request message; &lt;/li&gt;
        &lt;li&gt;Send port ComplexMessaging_PutCache picks up the service response and adds it to the cache, using the cache key from the original request; &lt;/li&gt;
        &lt;li&gt;Send port ComplexMessaging _SendServiceResponse picks up the service response and copies it to the output directory. &lt;/li&gt;
    &lt;/ol&gt;
    &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is a risk in this scenario that the object will exist in cache at the point of checking, but been removed by the time the cache is actually read. In this case the response from step 2 will be a passthrough of the original request – in the sample, this means the originating request will be copied to the output directory. Suspending the message may be a better option, but depending on the solution you may be able to cope with this differently. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132543"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132543" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/132543.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx</guid>
            <pubDate>Tue, 02 Jun 2009 03:11:26 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/132543.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/132543.aspx</wfw:commentRss>
        </item>
        <item>
            <title>BizTalk Cache Adapter</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx</link>
            <description>&lt;p style="TEXT-ALIGN: center"&gt;&lt;span style="FONT-SIZE: 10pt"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In a recent project we had a requirement for a configurable cache, residing on a BizTalk host and storing responses from WCF services which the BizTalk app had brokered. Producing this as a generic cache adapter was the preferred option, but project timescales didn't allow for it – instead I've written the adapter as an open source component which is available on CodePlex: &lt;a href="http://biztalkcacheadapter.codeplex.com/"&gt;BizTalkCacheAdapter&lt;/a&gt;, and which we're now making use of in the project. &lt;/p&gt;
&lt;p&gt;It's a simple design suitable for any situation where BizTalk is brokering services to consumers. The incoming request from the consumer is hashed to generate a cache key, and the response is stored in the cache against the request key. When future requests exactly match, they will receive the cached response; if the response doesn't exist in the cache, the service provider is invoked and the response is added to the cache. The adapter is independent of the cache store being used – currently the only option provided is &lt;a href="http://www.alachisoft.com/ncache/ncache_express.html"&gt;NCache Express&lt;/a&gt;, but extending it to use &lt;a href="http://www.danga.com/memcached/"&gt;memcached&lt;/a&gt; or &lt;a href="http://msdn.microsoft.com/en-us/data/cc655792.aspx"&gt;Velocity&lt;/a&gt; will be straightforward. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Overview &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The adapter uses context properties to store cache configuration, so it's suitable for orchestration or messaging solutions. Alongside the adapter on CodePlex is a sample project which demonstrates the approaches. The workflow is the same in both cases: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach1.png" /&gt; &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;The consumer sends a service request via the CacheXMLReceive pipeline, which checks if the message type is configured for caching, and promotes the &lt;em&gt;IsMessageCacheEnabled&lt;/em&gt; property; &lt;/li&gt;
    &lt;li&gt;If caching is enabled, a two-way message is sent to the cache adapter. This is a GET request, so the adapter checks the cache using the &lt;em&gt;MessageCacheKey&lt;/em&gt; context property – if the context property is not available, the adapter writes it by hashing the contents of the service request in the message body; &lt;/li&gt;
    &lt;li&gt;The response from the cache adapter promotes the &lt;em&gt;IsCached&lt;/em&gt; property, which identifies whether the response is in cache – if so, the body of the response message will be the cached service response, if not the body is the original service request which can be passed on to the service; &lt;/li&gt;
    &lt;li&gt;If &lt;em&gt;IsCached&lt;/em&gt; is false, the service is invoked and a one-way message containing the response is sent to the cache adapter. This is a PUT request, so the adapter adds the message body to the cache using the &lt;em&gt;MessageCacheKey&lt;/em&gt;; &lt;/li&gt;
    &lt;li&gt;The service response (either cached or from the provider) is returned to the consumer. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the messaging solution, the same workflow is carried out using subscriptions to the promoted cache configuration properties, and the various send ports. This workflow may not be suitable for more complex messaging solutions, where services are invoked through dynamic send ports – there is an alternative workflow which I'll cover in a &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter-samples.aspx"&gt;separate post.&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The only real complexity in the adapter is in putting the service response into the cache – the outgoing service request message has the cache configuration properties promoted, but the incoming response does not. In orchestration solutions this isn't a problem, as the cache properties can be stored as state in the orchestration instance. In messaging solutions, the cache properties are retained by temporarily adding them to the cache, keyed by the interchange ID of the service instance, and removing them when the response is added to the cache. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Configuration &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The cache adapter can be used with messages of any type, but with XML messages it can employ different cache configurations for different message types - e.g. a service to get current tax rates may configured to live for several days in the cache, while a service to get current exchange rates may use the same cache store, but be configured to expire after an hour. The &lt;strong&gt;CacheReceive&lt;/strong&gt; and &lt;strong&gt;CacheReceiveXml&lt;/strong&gt; pipelines contain properties for configuring the cache – it can be enabled/disabled for all messages, or (for the XML pipeline) only for configured message types: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach2.png" /&gt; &lt;/p&gt;
&lt;p&gt;Message-level configuration uses an SSO application store, which holds a &lt;strong&gt;MessageCacheConfigurationCollection&lt;/strong&gt; object in XML: &lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfigurationCollection&lt;/span&gt;&lt;span style="COLOR: blue"&gt; &lt;/span&gt;&lt;span style="COLOR: red"&gt;xmlns&lt;/span&gt;&lt;span style="COLOR: blue"&gt;=&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;http://schemas.sixeyed.com/CacheAdapter/2009&lt;/span&gt;"&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfigurations&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;http://schemas.sixeyed.com/CacheAdapterSample/2009#GetServerDateTime&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;http://schemas.xyz.com/2009#GetXYZ&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageType&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cacheLifespan&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt;&lt;/span&gt;PT10M&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;cacheLifespan&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;span style="COLOR: blue"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR: #a31515"&gt;messageCacheConfiguration&lt;/span&gt;&lt;span style="COLOR: blue"&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;... &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Caching is enabled for a message if: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;
    &lt;div&gt;&lt;em&gt;IsCacheEnabled&lt;/em&gt; is true on the pipeline AND&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/div&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;em&gt;IsMessageTypeConfigurationEnabled&lt;/em&gt; is false on the pipeline OR&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/li&gt;
        &lt;li&gt;
        &lt;div&gt;&lt;em&gt;IsMessageTypeConfigurationEnabled&lt;/em&gt; is true on the pipeline AND&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/div&gt;
        &lt;ul&gt;
            &lt;li&gt;the incoming message type has an entry in the &lt;strong&gt;MessageCacheConfigurationCollection&lt;/strong&gt; in SSO.&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt; &lt;/span&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The lifespan of the object put into cache will be either the &lt;em&gt;cacheLifespan&lt;/em&gt; specified in the &lt;strong&gt;MessageCacheConfiguration&lt;/strong&gt; in SSO, or the &lt;em&gt;defaultLifespan&lt;/em&gt; specified in the cache send port: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach3.png" /&gt; &lt;/p&gt;
&lt;p&gt;(The point at which the object is removed from cache will depend on the provider, some will remove it when its lifespan expires, others only when its lifespan expires and the cache is full or the cleanup schedule runs). &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Installation &lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For version 1.0.0.0, the CodePlex project comes with three project releases, which can be used independently or together: &lt;/p&gt;
&lt;ul style="MARGIN-LEFT: 38pt"&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapter.msi&lt;/strong&gt; - a BizTalk application MSI which can be imported and installed to your BizTalk server(s). The application contains the configuration schema and pipelines, so it can be used as-is, or the relevant artifacts can be moved to your own application; &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapter.Binaries.zip&lt;/strong&gt; – a ZIP file of the adapter binaries you can deploy manually. Use instead of the CacheAdapter MSI, if you don't want to deploy the whole BizTalk application; &lt;/li&gt;
    &lt;li&gt;
    &lt;div&gt;&lt;strong&gt;Sixeyed.CacheAdapter.CacheViewer.msi&lt;/strong&gt; – a Windows forms application which lets you view the contents of a cache store (the app uses the configuration components from the adapter management assembly, so it is also cache-provider agnostic):  &lt;/div&gt;
    &lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/eltonstoneman/060109_2108_BizTalkCach4.png" /&gt; &lt;/p&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;- a documentation release: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapter.chm&lt;/strong&gt; – documents the .NET assemblies of the adapter &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;- and two sample releases which should be deployed together: &lt;/p&gt;
&lt;ul style="MARGIN-LEFT: 38pt"&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapterSample.msi&lt;/strong&gt; – a BizTalk application MSI which has sample usage of the cache adapter, demonstrating orchestration and messaging approaches; &lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Sixeyed.CacheAdapterSample.Service.msi&lt;/strong&gt; – a WCF MSI which provides a service which the BizTalk app can cache. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pre-requisite for the initial release is the non-commercial &lt;a href="http://www.alachisoft.com/ncache/ncache_express.html"&gt;NCache Express&lt;/a&gt; to use as the cache provider. &lt;/p&gt;
&lt;p&gt;To add the sample message-level cache configuration to SSO, the &lt;a href="http://ssoconfigtool.codeplex.com/"&gt;SSO Config Tool&lt;/a&gt; can import the provided .ssoconfig file into SSO. &lt;/p&gt;
&lt;p&gt;I'll update the project to add a memcached provider, and write an updated post when it's available - and the same when Velocity is released. One advantage in having multiple providers would be in evaluating their performance against your expected caching load, so I'll look at extending the sample solution and adding some &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c8af583f-7044-48db-b7b9-969072df1689&amp;amp;DisplayLang=en"&gt;LoadGen&lt;/a&gt; scripts. &lt;/p&gt;
&lt;p&gt;And as &lt;a href="http://geekswithblogs.net/michaelstephenson/Default.aspx"&gt;Michael Stephenson&lt;/a&gt; commented, a nice alternative would be to move the caching up to the WCF layer as a behavior, so WCF requests would check the cache first. Two options for this – it can either be a client behaviour using a local cache store (which could be more performant and would have less impact on server resources, but requires the cache provider to be deployed client-side), or as an operation behaviour using a shared server-side cache (which could be more performant, depending on the type of messages being cached, would impact on server and network resource, but would make the caching transparent to consumers). The complexity is on caching the response message if not already cached – the cache key from the original message will have been lost, so there needs to be a different approach for maintaining state to correlate the WCF service request and response. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132542"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132542" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/132542.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx</guid>
            <pubDate>Tue, 02 Jun 2009 03:08:31 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/132542.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/06/01/biztalk-cache-adapter.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/132542.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Visualizing SOA’s Return on Investment</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/03/26/visualizing-soas-return-on-investment.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is the rather grand title of a WebCast I've recorded recently which tries to illustrate where the return on investment comes after moving to a SOA strategy. The video is on Digital Forum:  &lt;a href="http://www.digitalforumtv.com/#/Community/852"&gt;Visualizing SOA ROI&lt;/a&gt; , and the Open Source proof of concept it references is on CodePlex: &lt;a href="http://www.codeplex.com/ESBSimpleSamples"&gt;ESBSimpleSamples&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;In the WebCast I start with a blank Visual Studio solution and create a new Web app which consumes an existing service. All in it takes 3 lines of code and around 3 minutes of development (most of it spent correcting typos), and it doesn't require me to have any understanding of the underlying SOA infrastructure – in this case, Microsoft's ESB Guidance package sitting on BizTalk Server 2006 R2. Equally important, assuming the service we consume is in production, the testing and deployment effort needed for the new project is minimal. &lt;/p&gt;
&lt;p&gt;This is a rework of a presentation I did with a client where I wanted to show how quick and easy it is to use their SOA implementation. I had reservations of showing a code demonstration to an audience which included IT heads (IT Director and Solution Architects) and project management, but it was surprisingly well received, so I've reproduced it using services and components which are publicly available. &lt;/p&gt;
&lt;p&gt;Direct links to the references in the WebCast are here: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;ESB Guidance: &lt;a href="http://www.codeplex.com/esb"&gt;http://www.codeplex.com/esb&lt;/a&gt; 		&lt;/li&gt;
    &lt;li&gt;UK SOA/BPM User Group presentation: &lt;a href="http://sbug.org.uk/media/p/129.aspx"&gt;http://sbug.org.uk/media/p/129.aspx&lt;/a&gt; 		&lt;/li&gt;
    &lt;li&gt;Blog posts on ESB Guidance: &lt;a href="http://geekswithblogs.net/EltonStoneman/category/7947.aspx"&gt;http://geekswithblogs.net/EltonStoneman/category/7947.aspx&lt;/a&gt; 		&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=130437"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=130437" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/130437.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/03/26/visualizing-soas-return-on-investment.aspx</guid>
            <pubDate>Thu, 26 Mar 2009 18:36:18 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/130437.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/03/26/visualizing-soas-return-on-investment.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/130437.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Using WCF-Custom Bindings in Dynamic Ports</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/03/06/using-wcf-custom-bindings-in-dynamic-ports.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;BizTalk 2006 R2 ships with WCF adapters and pre-configured settings for common bindings - &lt;strong&gt;basicHttp&lt;/strong&gt; and &lt;strong&gt;wsHttp&lt;/strong&gt; being typically used for SOAP messaging. With a static port you can use the WCF-Custom adapter, select an existing binding and configure it further in the UI, with the full set of binding options available to you: &lt;/p&gt;
&lt;p&gt; 		&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/030609_1739_UsingWCFCus1.jpg" alt="" style="width: 446px; height: 565px;" /&gt; 	&lt;/p&gt;
&lt;p&gt;Here I'm using &lt;strong&gt;basicHttp&lt;/strong&gt;, but I've configured the &lt;em&gt;maxReceivedMessageSize&lt;/em&gt;, &lt;em&gt;sendTimeout&lt;/em&gt; and &lt;em&gt;transferMode&lt;/em&gt; settings to allow us to call long-running WCF services which return large responses. &lt;/p&gt;
&lt;p&gt;In a dynamic port, you're limited to the settings you can configure, as the &lt;a href="http://msdn.microsoft.com/en-us/library/bb245991.aspx"&gt;WCF Adapter Property Schema&lt;/a&gt; doesn't contain the full set of binding properties. You can set the &lt;em&gt;sendTimeout&lt;/em&gt; and &lt;em&gt;maxReceivedMessageSize&lt;/em&gt; on an outgoing message using code: &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;port(Microsoft.XLANGs.BaseTypes.TransportType) = "WCF-BasicHttp";  &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;requestMessage(WCF.MaxReceivedMessageSize) = 104857600;  &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;requestMessage(WCF.SendTimeout) = "00:10:00";  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;- but there's no way to access less common properties like &lt;em&gt;transferMode&lt;/em&gt; if you're using this approach. Originally this is how we were configuring our outgoing messages, using SSO to store the values used for the binding properties (see &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2009/02/25/receiving-large-wcf-response-messages-in-esb-guidance.aspx"&gt;Receiving large WCF response messages in ESB Guidance&lt;/a&gt;), but we soon ran into an issue with one of the BizTalk servers running out of memory when attempting to process a large WCF response message: &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;System.InsufficientMemoryException: Failed to allocate a managed memory buffer of 104857600 bytes. The amount of available memory may be low. ---&amp;gt; System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;   at System.ServiceModel.Diagnostics.Utility.AllocateByteArray(Int32 size)  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;basicHttp&lt;/strong&gt;, the &lt;em&gt;transferMode&lt;/em&gt; setting allows you to specify that messages should be streamed (one way or both ways), or buffered - the default is buffered, so when we receive the response message, although it will be streamed in the BizTalk stack, it is completely loaded into memory by the WCF stack. Note that WCF is trying to allocate the full value specified in &lt;em&gt;maxReceivedMessageSize&lt;/em&gt; – 100 Mb – even though we've set this as a practical maximum, and the actual incoming message was half that size. &lt;/p&gt;
&lt;p&gt;To remedy it, I've switched to using the WCF-Custom transport, and specifying &lt;strong&gt;basicHttp&lt;/strong&gt; with my additional settings in the &lt;em&gt;BindingConfiguration&lt;/em&gt; property: &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;port(Microsoft.XLANGs.BaseTypes.TransportType) = "WCF-Custom"; &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;requestMessage(WCF.BindingType) =  "basicHttpBinding"; &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;requestMessage(WCF.BindingConfiguration) =  "&amp;lt;binding name=\"basicHttpBinding\" sendTimeout=\"00:10:00\" maxReceivedMessageSize=\"104857600\" /&amp;gt;"; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt;The &lt;em&gt;BindingType&lt;/em&gt; needs to be specified in addition to the configuration. For the &lt;em&gt;BindingConfiguration&lt;/em&gt; value, the Properties page for a static WCF-Custom port allows you to export the settings, so you can configure it in the UI and then save the XML representation, rather than coding it all by hand. &lt;/p&gt;
&lt;p&gt;By shifting the &lt;em&gt;BindingConfiguration&lt;/em&gt; value to the SSO config store, we'll have the full range of WCF configuration available to change at run-time, so a switch to using &lt;strong&gt;wsHttp&lt;/strong&gt; or &lt;strong&gt;netTcp&lt;/strong&gt; bindings is just a setting change using the &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2008/06/29/sso-config-tool.aspx"&gt;SSO Config Tool&lt;/a&gt;, and a change to the endpoint address (which we configure in UDDI in this case). Originally I wanted finer control over what could be configured, so we could limit changes to a known set of properties. But having tried this approach I prefer it – it means switching bindings and adding or changing any settings can easily be done without modifying the solution – and I'll be recommending it as best practice. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129884"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129884" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/129884.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/03/06/using-wcf-custom-bindings-in-dynamic-ports.aspx</guid>
            <pubDate>Fri, 06 Mar 2009 23:38:49 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/129884.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/03/06/using-wcf-custom-bindings-in-dynamic-ports.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/129884.aspx</wfw:commentRss>
        </item>
        <item>
            <title>MSDTC Issue with Clustered BizTalk Host</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/02/23/msdtc-issue-with-clustered-biztalk-host.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We had an issue with one of our BizTalk estates with incoming messages being suspended if they were bigger than the large message threshold: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;A response message sent to adapter "WCF-BasicHttp" on Receive Location: "x" with URI:"y" is suspended. Error details: There was a failure executing the response(receive) pipeline: "z" Source: "Unknown " Send Port: "x" URI: "y" Reason: 0x8004d027   &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The error message wasn't particularly helpful but the reason code &lt;strong&gt;0x8004d027&lt;/strong&gt; had a few threads and posts relating to DTC. This made sense as we're in a distributed environment so DTC will be used to create message fragments under a transaction, if the whole message exceeds the threshold size. Using Web Service Studio I found the expected message size, and setting the large message threshold above that figure fixed the problem so that seemed to confirm it.  &lt;/p&gt;
&lt;p&gt;We finally tracked the issue down to permissions on the cluster where MSDTC was running. Buried in the Event Log for the BizTalk host suspending the messages was this error: &lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Courier New; font-size: 10pt;"&gt;The application could not connect to MSDTC because of insufficient permissions. Please make sure that the identity under which the application is running has permission to access the cluster. Please refer to MSCS documentation on how to grant permissions. Error Specifics: d:\nt\com\complus\dtc\dtc\msdtcprx\src\dtcinit.cpp:652, Pid: 6772 No Callstack, CmdLine: "C:\Program Files\Microsoft BizTalk Server 2006\BTSNTSvc.exe" -group "BizTalk Group" -name "x" -btsapp "y"  &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This was logged when the BizTalk service started, which had been the day before we found the suspended messages, so I didn't see the connection. This post from Ben Cops: &lt;a href="http://bencops.blogspot.com/2008/12/error-on-installing-sso-on-clustered.html"&gt;http://bencops.blogspot.com/2008/12/error-on-installing-sso-on-clustered.html&lt;/a&gt; pointed me in the right direction, and the steps for adding permissions are simple - the only oddity is that you set permissions at the cluster level, not at the resource level: &lt;/p&gt;
&lt;ul style="margin-left: 54pt;"&gt;
    &lt;li&gt;Open Cluster Administrator &lt;/li&gt;
    &lt;li&gt;Right-click the cluster (the topmost node) and select Properties &lt;/li&gt;
    &lt;li&gt;Under Security, add the BizTalk user group with Full Control &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This and a host restart fixed the issue. Along the way we did notice a couple of other issues in our MSDTC configuration which we tracked down and fixed with DTCPing. Worth noting that in Windows Server 2003 the properties for MSDTC under &lt;strong&gt;dcomcnfg&lt;/strong&gt; may not correctly reflect the registry settings, so while you think DTC security is configured like this: &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/022309_1748_MSDTCIssuew1.png" /&gt; 	&lt;/p&gt;
&lt;p&gt;- it may actually be configured like this: &lt;/p&gt;
&lt;p&gt; 		&lt;img alt="" src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/022309_1748_MSDTCIssuew2.jpg" /&gt; 	&lt;/p&gt;
&lt;p&gt;The DTCPing log will tell you what registry settings are in use, and the BizTalk Best Practices Analyzer will warn you if the DTC security settings are incorrect, so worth double-checking this. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129621"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129621" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/129621.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/02/23/msdtc-issue-with-clustered-biztalk-host.aspx</guid>
            <pubDate>Mon, 23 Feb 2009 23:48:55 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/129621.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/02/23/msdtc-issue-with-clustered-biztalk-host.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/129621.aspx</wfw:commentRss>
        </item>
        <item>
            <title>An Infrastructure Design for ESB Guidance</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2009/02/02/an-infrastructure-design-for-esb-guidance.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Our ESB Guidance project is nearing code-completion and we're running System Test on an infrastructure which is suitable for production use. Designed for performance, reliability and scalability, we use servers in a combination of NLB farms, Windows clusters and SQL clusters. Shown below is a modified version of the layout, focusing on the BizTalk landscape: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/020209_0808_AnInfrastru1.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;A few of the design decisions are worth looking at: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;em&gt;Coordination Services&lt;/em&gt; run a host for Scheduled Task and FTP adapters, building itinerary requests from received messages. Both adapters are unable to flag an incoming message as being in-process, so are not safe on multiple instances – we have two servers in an active/passive Windows cluster to provide redundancy; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Itinerary Services&lt;/em&gt; run a host for incoming itinerary requests from the SOAP adapter. This is instance-safe, so we have two servers configured in a  farm for redundancy and performance; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Itinerary Processing&lt;/em&gt; runs a host for the custom orchestration we have for handling calls to WCF service providers (not shown in this diagram, but running on a separate Web farm and SQL instance). All BizTalk servers run instances of this host, so any with capacity can service calls; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;Enterprise Single Sign-On&lt;/em&gt; is located it on the Windows cluster with the Coordination Services, as it cannot run under an NLB farm. The Coordination Service is expected to have spare capacity, so hosting SSO shouldn't impact performance; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;UDDI Services &lt;/em&gt;run on the BizTalk NLB farm with the Itinerary Services. A small compromise here from the ideal of having a separate UDDI host, but resolver calls will all be made during Itinerary Processing and we use a custom UDDI resolver which holds the cache indefinitely (until manually invalidated when a change is promoted to the UDDI Service), so after the initial warm-up, UDDI Services will have negligible usage; &lt;/li&gt;
    &lt;li&gt;
    &lt;div&gt;&lt;em&gt;UDDI Database&lt;/em&gt; runs on the same SQL instance as the BizTalk databases. The second small compromise – breaking the cardinal rule that BizTalk should have a dedicated SQL instance with dedicated hardware… As UDDI calls will be minimal, this is a worthwhile performance trade to get the redundancy of having UDDI on the SQL cluster. &lt;/div&gt;
    &lt;p&gt;  &lt;/p&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The design is intended to cope with a relatively low initial throughput – 250,000 messages in the first year, 98% of which will be a few kilobytes, 2% running into megabytes. BizTalk servers all running Enterprise Edition in a Group, with just Microsoft.Practices.ESB and our custom application installed. Currently the BizTalk servers are running single quad-core CPUs with 4Gb RAM. &lt;/p&gt;
&lt;p&gt;  &lt;/p&gt;
&lt;p&gt; Our next task is to run some simulated load through the setup and modify the host layout or physical capacity if necessary. I'll cover the load testing results in a future post. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129137"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=129137" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/129137.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2009/02/02/an-infrastructure-design-for-esb-guidance.aspx</guid>
            <pubDate>Mon, 02 Feb 2009 14:08:46 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/129137.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2009/02/02/an-infrastructure-design-for-esb-guidance.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/129137.aspx</wfw:commentRss>
        </item>
        <item>
            <title>BizTalk Deployments with PowerShell</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2008/12/10/biztalk-deployments-with-powershell.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As part of my first look at &lt;a href="http://www.codeplex.com/esb/Release/ProjectReleases.aspx?ReleaseId=20234"&gt;ESB Guidance 2.0&lt;/a&gt; (which has some excellent enhancements which I'll post about shortly) I've been interested in the way the sample solutions are deployed. The P&amp;amp;P team have put together PowerShell scripts which take care of the usual things you'd find in a deployment scenario – stopping services, creating applications, adding resources and bindings.  &lt;/p&gt;
&lt;p&gt;In a Continuous Integration environment, you'd typically want to deploy to a BizTalk instance as part of the build process, to ensure the application configuration is valid, and as a prerequisite for running unit and integration tests. Currently I do this with MSBuild scripts using a variety of community, Sdc and custom tasks, and command-line tools. It makes for fragmented scripts that are difficult to read and maintain, and can be fragile to execute. &lt;/p&gt;
&lt;p&gt;In the PowerShell version a central script isolates the complexity for common functions, and then the individual install scripts use a neat, readable and hugely intuitive syntax. This is a complete install script for one of the sample solutions (&lt;em&gt;MultipleWebServices_install.ps1&lt;/em&gt;), which builds and then deploys the artifacts:&lt;span style="font-family: Courier New;"&gt; 		&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: purple;"&gt;$relativePath&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"..\.."&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: purple;"&gt;$samplesPath&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$solutionPath&lt;/span&gt;&lt;span style="color: red;"&gt;+&lt;/span&gt;&lt;span style="color: maroon;"&gt;"\Samples\MultipleWebServices"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;. ..\..\..\..\&lt;/span&gt;&lt;span style="color: blue;"&gt;Core&lt;/span&gt;&lt;span style="color: black;"&gt;\&lt;/span&gt;&lt;span style="color: blue;"&gt;Install&lt;/span&gt;&lt;span style="color: black;"&gt;\&lt;/span&gt;&lt;span style="color: blue;"&gt;Scripts&lt;/span&gt;&lt;span style="color: black;"&gt;\&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;ESBFunctions.ps1&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: mediumblue;"&gt;BuildItinerarySolution &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;{ &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: blue;"&gt;param&lt;/span&gt;&lt;span style="color: black;"&gt;([&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;System.String&lt;/span&gt;&lt;span style="color: black;"&gt;] &lt;/span&gt;&lt;span style="color: purple;"&gt;$buildType&lt;/span&gt;&lt;span style="color: black;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &amp;amp;&lt;/span&gt;&lt;span style="color: purple;"&gt;$FrameworkPath&lt;/span&gt;&lt;span style="color: maroon;"&gt;"\v3.5\MSBuild.exe"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$relativePath&lt;/span&gt;&lt;span style="color: maroon;"&gt;"\GlobalBank.ESB.Samples.MultipleWebServices.sln"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;/&lt;/span&gt;&lt;span style="color: blue;"&gt;t&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;&lt;span style="color: blue;"&gt;Rebuild&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;/&lt;/span&gt;&lt;span style="color: blue;"&gt;p&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;&lt;span style="color: blue;"&gt;Configuration&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: purple;"&gt;$buildType&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;BuildItinerarySolution&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: blue;"&gt;Debug&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;StopBTSApplication&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Microsoft.Practices.ESB"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;StopBTSApplication&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"GlobalBank.ESB"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;StopBTSServices&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;ImportBTSResource&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"GlobalBank.ESB"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"BizTalkAssembly"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$relativePath&lt;/span&gt;&lt;span style="color: maroon;"&gt;"\Source\ESB.MultipleWebServices.Maps\bin\Debug\ESB.MultipleWebServices.Maps.dll"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;ImportBTSResource&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"GlobalBank.ESB"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"BizTalkAssembly"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$relativePath&lt;/span&gt;&lt;span style="color: maroon;"&gt;"\Source\ESB.MultipleWebServices.Orchestrations\bin\Debug\ESB.MultipleWebServices.Orchestrations.dll"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;GacOperation&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"-if"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$relativePath&lt;/span&gt;&lt;span style="color: maroon;"&gt;"\Source\ESB.MultipleWebServices.Maps\bin\Debug\ESB.MultipleWebServices.Maps.dll"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;GacOperation&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"-if"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$relativePath&lt;/span&gt;&lt;span style="color: maroon;"&gt;"\Source\ESB.MultipleWebServices.Orchestrations\bin\Debug\ESB.MultipleWebServices.Orchestrations.dll"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;ImportBinding&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"GlobalBank.ESB"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$relativePath&lt;/span&gt;&lt;span style="color: black;"&gt;\&lt;/span&gt;&lt;span style="color: blue;"&gt;Install&lt;/span&gt;&lt;span style="color: black;"&gt;\&lt;/span&gt;&lt;span style="color: blue;"&gt;Binding&lt;/span&gt;&lt;span style="color: black;"&gt;\&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;GlobalBank.ESB.MultipleWebServices_Bindings.xml&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;StartBTSApplication&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Microsoft.Practices.ESB"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;StartBTSApplication&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"GlobalBank.ESB"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: blue; font-family: Courier New;"&gt;StartBTSServices&lt;/span&gt; 		&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The common script (&lt;em&gt;ESBFunctions.ps1&lt;/em&gt;) defines the main functions – &lt;em&gt;ImportBTSResource&lt;/em&gt; etc. – so the logic in the individual scripts is very clean. Common functions make use of PowerShell commands, the BizTalk Explorer OM, BTSTask and custom tools as appropriate, so there's still a variety of tools under the covers, but the common script is a facade over them all. This makes the install scripts neater and abstracts them from the actual implementation of the functions. Below are snippets for the functions to stop and to remove a BizTalk application: &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: mediumblue;"&gt;StopBTSApplication &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;{  &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: blue;"&gt;param&lt;/span&gt;&lt;span style="color: black;"&gt;([&lt;/span&gt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: purple;"&gt;$appName&lt;/span&gt;&lt;span style="color: black;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: purple;"&gt;$exp&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: cadetblue;"&gt;New-Object&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: purple;"&gt;$exp&lt;/span&gt;&lt;span style="color: black;"&gt;.&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;ConnectionString&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$btsConnectionString&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: purple;"&gt;$app&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$exp&lt;/span&gt;&lt;span style="color: black;"&gt;.&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;Applications&lt;/span&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;span style="color: purple;"&gt;$appName&lt;/span&gt;&lt;span style="color: black;"&gt;] &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;$app&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;-eq&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$null&lt;/span&gt;&lt;span style="color: black;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;    { &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;        &lt;/span&gt;&lt;span style="color: cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Application "&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$appName&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;" not found"&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: cadetblue;"&gt;-fore&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: blue;"&gt;Red&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;    } &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: blue;"&gt;else&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;    { &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;        &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt;&lt;span style="color: black;"&gt;(&lt;/span&gt;&lt;span style="color: purple;"&gt;$app&lt;/span&gt;&lt;span style="color: black;"&gt;.&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;Status&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;-ne&lt;/span&gt;&lt;span style="color: black;"&gt; 2) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;        { &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;            &lt;/span&gt;&lt;span style="color: green;"&gt;#full stop of application &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;            &lt;/span&gt;&lt;span style="color: purple;"&gt;$null&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$app&lt;/span&gt;&lt;span style="color: black;"&gt;.&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;Stop&lt;/span&gt;&lt;span style="color: black;"&gt;(63) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;            &lt;/span&gt;&lt;span style="color: purple;"&gt;$null&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;=&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$exp&lt;/span&gt;&lt;span style="color: black;"&gt;.&lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;SaveChanges&lt;/span&gt;&lt;span style="color: black;"&gt;() &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;            &lt;/span&gt;&lt;span style="color: cadetblue;"&gt;Write-Host&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Stopped application: "&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$appName&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;        } &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;    } &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: mediumblue;"&gt;RemoveBTSApplication &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="color: black; font-family: Courier New; font-size: 9pt;"&gt;{  &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: blue;"&gt;param&lt;/span&gt;&lt;span style="color: black;"&gt;([&lt;/span&gt;&lt;span style="color: blue;"&gt;string&lt;/span&gt;&lt;span style="color: black;"&gt;]&lt;/span&gt;&lt;span style="color: purple;"&gt;$appName&lt;/span&gt;&lt;span style="color: black;"&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;  &lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: cadetblue;"&gt;Write-Output&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: maroon;"&gt;"Removing BTS Application "&lt;/span&gt;&lt;span style="color: red;"&gt;+&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: purple;"&gt;$appName&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-family: Courier New; font-size: 9pt;"&gt;&lt;span style="color: black;"&gt;    &lt;/span&gt;&lt;span style="color: saddlebrown;"&gt;BTSTask.exe&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: blue;"&gt;RemoveApp&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;span style="color: red;"&gt;/&lt;/span&gt;&lt;span style="color: blue;"&gt;A&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;&lt;span style="color: purple;"&gt;$appName&lt;/span&gt;&lt;span style="color: black;"&gt; 			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin-left: 36pt;"&gt;&lt;span style="font-size: 9pt;"&gt;&lt;span style="color: black; font-family: Courier New;"&gt;}&lt;/span&gt; 		&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There's some complexity in these common functions, but they're all tried and tested by the Patterns &amp;amp; Practices team. This is a new approach for the ESB Guidance installs (v1.0 used a combination of batch files to deploy the samples), but I don't think there are any inherent dependencies on BTS 2009 so this approach and the common script should work for BTS 2006 solutions. I'm going to look at migrating my current build scripts to this approach as it's so much simpler to work with, and the execution doesn't rely on chaining together unrelated tasks in MSBuild.  &lt;/p&gt;
&lt;p&gt;The ESBG samples specifically name resources to deploy, whereas my current scripts run dynamically over whichever artifacts they find, but Bart De Smet has a nice &lt;a href="http://bartdesmet.net/blogs/bart/archive/2008/02/16/invoking-powershell-scripts-from-msbuild.aspx"&gt;MSBuild task for running PowerShell scripts&lt;/a&gt;, which takes parameters so that's one option, and generating PS scripts using the &lt;a href="http://geekswithblogs.net/EltonStoneman/archive/2008/10/04/executet4template-msbuild-task-updated.aspx"&gt;ExecuteT4Template task&lt;/a&gt; is another. &lt;/p&gt;
&lt;p&gt;If I do get this running for BizTalk 2006 R2 solutions, I'll post a working set of sample scripts.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127799"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127799" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/127799.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2008/12/10/biztalk-deployments-with-powershell.aspx</guid>
            <pubDate>Thu, 11 Dec 2008 05:09:56 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/127799.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2008/12/10/biztalk-deployments-with-powershell.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/127799.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Introducing: BizTalkCop</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2008/11/14/introducing-biztalkcop.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To make good on a rash comment around the lack of standards-enforcement for BizTalk, I've put together a set of FxCop rules which allow you to run static analysis over BizTalk solutions. It covers all aspects by running rules against compiled artifact assemblies and configured BizTalk applications. It's on CodePlex here: &lt;a href="http://www.codeplex.com/BizTalkCop"&gt;BizTalkCop&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;The first release(1.0) contains a full ruleset for validating BizTalk application artifact names, based on &lt;a href="http://www.traceofthought.net/misc/BizTalk%20Naming%20Conventions.htm"&gt;Scott Colestock's naming conventions&lt;/a&gt;. By default the rules are more strict in places, but they're configurable so you can modify them to suit your own standards. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Usage &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Currently BizTalk projects don't integrate fully with static analysis in VS 2005, so you'll need the separate FxCop UI – latest version is &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9aeaa970-f281-4fb0-aba1-d59d7ed09772&amp;amp;DisplayLang=en"&gt;FxCop 1.36&lt;/a&gt;. Once you've installed FxCop, run the BizTalkCop installer and it will add &lt;em&gt;BizTalkCop.Rules.dll&lt;/em&gt; and &lt;em&gt;BizTalkCop.Rules.chm&lt;/em&gt; to the FxCop rules folder (default: Program Files\Microsoft FxCop 1.36\Rules). Open FxCop and there are three steps to configure your BizTalk project: &lt;/p&gt;
&lt;p&gt;1. Add Targets &lt;/p&gt;
&lt;p&gt;Add the compiled BizTalk assemblies you want to check to the FxCop project. For compiled artifacts, BizTalkCop covers orchestrations, maps, schemas and pipelines so you can add any assemblies that contain these: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/111408_1034_Introducing1.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;2. Select Rules &lt;/p&gt;
&lt;p&gt;If you've used the default installation, then the BizTalkCop rule set should be listed in the Rules tab (if not you'll need to navigate to add it). Check BizTalkCop and uncheck all the others: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/111408_1034_Introducing2.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;3. Set up Application Configuration &lt;/p&gt;
&lt;p&gt;In order to validate the configured BizTalk Application, you'll need to specify the location of your management database, and the name of the Applications to check. Open the &lt;em&gt;ApplicationConfig&lt;/em&gt; rule properties (this is a dummy rule which is only there to capture BizTalk Server config), and modify the Settings to specify your server, and the Applications to run over (semi-colon separated if more than one) – you only need to do this once, and all Application rules will use these settings: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/111408_1034_Introducing3.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;When you run FxCop it'll list all the rule failures, some of which may have multiple issues (e.g. ReceiveLocationNamesShouldIndicateTransport will flag an issue for every configured location that doesn't have its transport type as a suffix). There should be no locks on targets, so you can change the artifacts and recompile, or edit application config with FxCop open, and then re-run it. &lt;/p&gt;
&lt;p&gt;Most rules are configurable, so you can modify the prefixes and suffixes to suit your standards, or ignore any rules you don't care for. Save the project as a .FxCop file and you can integrate this into your build process using the &lt;a href="http://msbuildtasks.tigris.org/"&gt;MSBuild Community Tasks.&lt;/a&gt; 	&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Development&lt;/strong&gt; 	&lt;/p&gt;
&lt;p&gt;There's potential for rules to cover a lot more than the "Naming" category. Certain of the recommendations in the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=98ecf11a-9a8e-4939-8cef-2bc5536dc792&amp;amp;DisplayLang=en"&gt;BizTalk Performance Optimization Guide&lt;/a&gt; are candidates for a "Performance" category,  and there are a few gotchas that could be avoided with warnings from a "Design" category. I'm not planning to add these for a while, but if you want to get involved let me know and I'll add you as a contributor. &lt;/p&gt;
&lt;p&gt;FxCop runs over compiled assemblies, so introducing it to BizTalk meant for a few workarounds. If you want to extend BizTalkCop by adding new rules, there are a set of base classes which will help: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;em&gt;RuleBase&lt;/em&gt; – general base class for rules using normal introspection over classes; contains methods for determining if targets are maps, schemas etc; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;ConfiguredRuleBase &lt;/em&gt;– base class for rules which have default setting values which can be overridden in the project file; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;ApplicationRuleBase&lt;/em&gt; – base class for rules analysing BizTalk Applications; wraps the Explorer OM (so not good for 64-bit) to get the current config; &lt;/li&gt;
    &lt;li&gt;&lt;em&gt;OrchestrationRuleBase&lt;/em&gt; – base class for analysing Orchestrations; typically the compiled code is too dense for analysis, so the base class exposes methods for accessing the shape and OM configuration. This is stored as XML in the compiled class, and the base class provides XPath helpers to access it. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code for running the rule is quite straightforward, although tracking down the XML elements to check can be fiddly for orchestration rules (if you can find any schemas for the shape or OM XML, let me know and I'll modify it all to use entity classes). The source code contains a sample BizTalk project which fails all known rules, so you can add to this to check your own rules run as expected. &lt;/p&gt;
&lt;p&gt;Quite possibly the CSD have something like this in place for the VS 2008 integration coming in BizTalk Server 2009. If not, it should be a trivial job to migrate these rules to run under VS, and in any case the ability to separate them out for running in the build should be useful. &lt;/p&gt;
&lt;p&gt;I've run the rules over a few solutions and they've been accurate, but if you come across any issues, log them on CodePlex and I'll have a look. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127018"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=127018" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/127018.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2008/11/14/introducing-biztalkcop.aspx</guid>
            <pubDate>Fri, 14 Nov 2008 16:36:06 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/127018.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2008/11/14/introducing-biztalkcop.aspx#feedback</comments>
            <slash:comments>10</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/127018.aspx</wfw:commentRss>
        </item>
        <item>
            <title>ESB Guidance Demonstration: “TriathlonResults”</title>
            <link>http://geekswithblogs.net/EltonStoneman/archive/2008/10/25/esb-guidance-demonstration-triathlonresults.aspx</link>
            <description>&lt;p style="text-align: center;"&gt;&lt;span style="font-size: 10pt;"&gt;[Source: &lt;a href="http://geekswithblogs.net/EltonStoneman"&gt;http://geekswithblogs.net/EltonStoneman&lt;/a&gt;] &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;At the SBUG meeting last week, my session on &lt;a href="http://sbug.org.uk/media/p/129.aspx"&gt;"ESB Guidance: A Real-World Implementation&lt;/a&gt;" was meant to end with a demonstration, but we ran out of time - and in any case what I'd intended to show was probably a bit ambitious, with plenty of this-is-bound-to-go-wrong points.  &lt;/p&gt;
&lt;p&gt;But I've spent some time making it more solid and the code is available now on MSDN Code Gallery: &lt;a href="http://code.msdn.microsoft.com/ESBTriathlonResults"&gt;&lt;strong&gt;ESB Guidance 1.0 Demonstration: TriathlonResults&lt;/strong&gt;&lt;/a&gt;, if you want to have a look. You'll need an environment with BizTalk 2006 R2 and ESB Guidance 1.0 set up to run it, but I'm looking at putting together a Webcast to give a walkthrough.&lt;span style="background-color: yellow;"&gt;&lt;strong&gt; 			&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Overview &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The demonstration involves a set of systems which each have custom integrations to a central system, and shows two SOA approaches for integrating them with BizTalk and ESB Guidance. The first approach is a partial migration, where the client systems are unchanged, but the central system picks up messages directed through ESBG. The second is a "full" SOA migration, where the clients are changed to integrate directly with ESBG. &lt;/p&gt;
&lt;p&gt;For the sake of an interesting demo, the systems are contrived to be unusual. They represent different systems for recording an athlete's time in a sector of a triathlon – each having a different UI and a different integration approach. The first sector - the swim - is recorded from a console app: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/102508_0609_ESBGuidance1.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt; The second – the bike – from a WinForms app: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/102508_0609_ESBGuidance2.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;And the third – the run – from an Excel 2003 workbook with some VBA script: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/102508_0609_ESBGuidance3.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;The integrations add results to a central database, which has a particularly poor web front-end: &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geekswithblogs.net/images/geekswithblogs_net/EltonStoneman/102508_0609_ESBGuidance4.png" alt="" /&gt; 	&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pre-requisites &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Windows Server 2003  with IIS &amp;amp; UDDI Services installed; SQL Server 2005; BizTalk Server 2006 R2; ESB Guidance 1.0.  &lt;/p&gt;
&lt;p&gt;The sample expects everything to live on &lt;em&gt;localhost&lt;/em&gt;, and uses a SQL Server login so you need to have mixed authentication and named pipes enabled in your SQL Server instance. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Installation &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Two steps after downloading the code – build and deploy the &lt;em&gt;TriathlonResults.Phase1&lt;/em&gt; solution (you'll need to modify the BizTalk projects to point to your own management database), then run the &lt;em&gt;Deploy.cmd&lt;/em&gt; script (it'll ask for the name of your SQL Server – just use "." for a local un-named instance).  &lt;/p&gt;
&lt;p&gt;This will create: &lt;/p&gt;
&lt;ul style="margin-left: 38pt;"&gt;
    &lt;li&gt;two SQL databases – &lt;em&gt;TriathlonResults&lt;/em&gt; and &lt;em&gt;TriathlonStaging&lt;/em&gt;; &lt;/li&gt;
    &lt;li&gt;a SQL login – &lt;em&gt;TriathlonResults&lt;/em&gt;; &lt;/li&gt;
    &lt;li&gt;a BizTalk application  - &lt;em&gt;TriathlonResults&lt;/em&gt;; &lt;/li&gt;
    &lt;li&gt;two IIS virtual directories – &lt;em&gt;TriathlonResults.Web&lt;/em&gt; and &lt;em&gt;TriathlonResults.Central&lt;/em&gt;.   &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the Shortcuts folder under the solution root you'll have links to the various client apps, and to the website which shows the full results from the central system. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 0 &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the starting point, with each system integrating to the central results service in a custom way: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;Console app:&lt;/span&gt; receives user input and outputs as a delimited flat file; a central console app runs a FileSystemWatcher over the expected location, parses the flat file and inserts the record to the central database; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;WinForms app:&lt;/span&gt; receives user input and sends the sector result as a Web service call to the central service, which inserts the record to the central database; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;Excel workbook:&lt;/span&gt; receives user input and inserts the result as a record in a staging database; a trigger on the staging table retrieves the new record and inserts it to the central database. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To see this, run &lt;em&gt;SetupPhase0.cmd&lt;/em&gt; and input some results. Usage of the client apps should be fairly straightforward – choose Athlete id=1 and Race id=1 to use known reference data, and refresh the web page for the first race after each input. You should see the sector times displayed after you enter them. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 1 &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the first SOA approach, showing an option for partial migration. Here the central result-recording Web service has been exposed as a service through ESBG, and the clients all use the central service. The WinForms client has been changed to invoke the ESBG call directly, but the other systems are unchanged and a BizTalk app picks up their output and submits it to the ESB: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;Console app:&lt;/span&gt; flat file output is now monitored by a BizTalk FILE Receive Location. The pipeline for the location parses the flat file into a known schema, and adds the itinerary details as context properties; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;WinForms app:&lt;/span&gt; uses a typed Service Request class to submit messages to ESBG directly. This is a proxy class which deals with wrapping the message in an ESBG itinerary, and submitting it to the on-ramp; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;Excel workbook:&lt;/span&gt; the trigger on the staging database is disabled and replaced with a SQL Receive Location which polls the staging table for unprocessed records. The pipeline adds itinerary details to the context; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;TriathlonResults BizTalk app:&lt;/span&gt; for the FILE and SQL Receive Locations, the BizTalk app has custom orchestrations which map incoming messages to the contract for the Web service, and submit the request. The send port &lt;em&gt;DynamicRequestResponse&lt;/em&gt; subscribes to any pre-formed itinerary message, so this picks up the message from the WinForms app, which doesn't require any specific workflow. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To use, close down any client apps you have running, run &lt;em&gt;SetupPhase1.cmd&lt;/em&gt;, open the clients and input some results. The command clears down the results DB, so you should start with an empty results page on the website. As you use the clients you can confirm they're using ESBG by checking HAT. You'll probably also notice that the WinForms app responds more slowly when you submit a result. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 2 &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is a full SOA migration, where the consumers are aware of the mechanism for requesting services, unlike the Phase 1 approach where this was abstracted away from the legacy apps. All client apps are changed here to invoke the ESBG service request directly: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;Console app:&lt;/span&gt; now uses the typed Service Request used by the WinForms app to build the ESBG message and submit it. Flat file no longer generated; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;WinForms app:&lt;/span&gt; unchanged from Phase 1; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;Excel Workbook:&lt;/span&gt; the typed Service Request is registered as a COM-callable Type Library and referenced from the Workbook. The VBA instantiates, populates and submits the ESBG message. Staging database no longer used; &lt;/li&gt;
    &lt;li&gt;&lt;span style="text-decoration: underline;"&gt;TriathlonResults BizTalk app:&lt;/span&gt; the SQL and FILE receive locations are no longer used, all incoming messages are of the expected itinerary type and are all dealt with by the &lt;em&gt;DynamicRequestResponse&lt;/em&gt; port. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To use, close down any client apps you have running, run &lt;em&gt;SetupPhase2.cmd&lt;/em&gt;, open the clients and input some results. Again, you should start with an empty results page on the website and can use HAT to confirm messages are going through BizTalk. You'll notice now that all the apps are responding more slowly when you submit a result. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Notes &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Phase 1 approach is a pragmatic one, realising some of the benefits expected in SOA at the cost of others. We have reuse of loosely-coupled services, a centralised discoverable service repository, and centralised message flow. We don't have a common communication mechanism and we haven't got away from bespoke formats and protocols. In some environments this may be as far as the migration goes, if service consumers can't be modified. It has the benefit of being transparent to consumers, but with bespoke mapping and configuration for each consumer it will have the largest custom codebase – taking more effort to develop and maintain. &lt;/p&gt;
&lt;p&gt;Phase 2 gives us the benefits of Phase 1, plus we are now using a single entry point to the ESB and consumers are submitting messages of known types which can be verified against the service contract schemas held in BizTalk. This particular implementation sees all the apps using a .NET component to abstract the work of creating the itinerary. This means consumers need no knowledge of BizTalk or ESB Guidance, but has the complication of distributing and maintaining that assembly. Consumers could use any approach to build their requests, provided they can understand XML and SOAP. &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126102"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=126102" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/EltonStoneman/aggbug/126102.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>EltonStoneman</dc:creator>
            <guid>http://geekswithblogs.net/EltonStoneman/archive/2008/10/25/esb-guidance-demonstration-triathlonresults.aspx</guid>
            <pubDate>Sat, 25 Oct 2008 12:10:16 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/EltonStoneman/comments/126102.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/EltonStoneman/archive/2008/10/25/esb-guidance-demonstration-triathlonresults.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/EltonStoneman/comments/commentRss/126102.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>