Posts Tagged ‘Administration’

I just updated three of my useful BizTalk PowerShell scripts in some cases fixing some small bugs, improving performance and in other cases adding also new capabilities.

PowerShell to configure Default Dynamic Send Port Handlers for each Adapter: This is a simple script that allows you to configure the default send handlers associated with all the existing Dynamic Send ports in your environment

  • In this new release I fixed some small bugs in the code that were not allowing the script to work as expected.

Check more about the script here: BizTalk DevOps: How to configure Default Dynamic Send Port Handlers with PowerShell

The full script can be found and download on Microsoft TechNet Gallery:
PowerShell to configure Default Dynamic Send Port Handlers for each Adapter (3.0 KB)
Microsoft TechNet Gallery

 

PowerShell to Configure the Default Send Handler for each static Send Port: This is a simple script that allows you to configure the Send handler associated with all the existing Static Send Ports in your environment independently of the adapter that is configured.

  • In this new release I fixed some small inconsistencies in the code, nevertheless in this case the previous script was working fine.

Check more about the script here: BizTalk DevOps: Configure the Default Send Handler as the Send Handler for each existing static Send Ports with PowerShell

The full script can be found and download on Microsoft TechNet Gallery:
PowerShell to Configure the Default Send Handler for each static Send Port (3.0 KB)
Microsoft TechNet Gallery

 

Monitoring BizTalk Server Ports with Auto-Healing capabilities with PowerShell: This is a simple script that allows you to monitor your BizTalk environment for disabled receive locations and stopped or unenlisted send ports, and automatically resume then according to certain conditions, using PowerShell.

In this new release:

  • I improved the general performance of the script
  • And add a new feature to the script: the ability to save a copy of the monitor report in the hard drive or a shared folder.

Check more about the script here: BizTalk DevOps: Monitor your BizTalk environment using PowerShell –Monitoring Ports (Stopped/disabled/unelisted) with Auto-Healing capabilities

The script can be found and download on Microsoft TechNet Gallery:
Monitoring BizTalk Server Ports with Auto-Healing capabilities with PowerShell (14.0 KB)
Microsoft TechNet Gallery

 

So, why these script are important?

All of these task can be easily made manually but they are time consuming tasks, special the monitor task if you don’t have the proper monitor tools like BizTalk360 or other tools available in the market. These PowerShell scripts allows you to automate and streamline these tasks saving us a considerable amount of time.

THESE POWERSHELL ARE PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.

In the sequence of my last two post (here and here) and following the same topic, in order to finalize it, let’s talk about the last option and see how we can accomplish the same goal but this type configuring the Send Handler for existing static Send Ports in your environment.

Well, the two previous post are, in my opinion, more critical than this one for se simple reason that the default BizTalk installation will had ports in your environment that needs to be configure if you want to configure BizTalk Host in a High Availability way, i.e., dedicate logical hosts to run specific areas of functionality such as receiving messages, sending messages, processing orchestrations or tracking data.

However, and although less critical, static send ports can also be a problem in some scenarios, for example:

  • If you install ESB Toolkit before configuring your hosts for each functionality, because during the ESB Toolkit installation it will also be created a static send port call “ALL.Exceptions” that connects with SQL “EsbExceptionDb” database. And this port will be configured with the default send handler (at that time) configured in your environment, that is by default the “BizTalkServerApplication”
  • but also if you reach to an existing environment, already containing several BizTalk Applications running, that is not configured according to best practices in terms of host and host instances (dedicate logical hosts for each functionality).

Once again, we need to do basically do the same steps described in my last two posts to accomplish the task of deleting “BizTalkServerApplication”, this time as a send handler of each adapter:

  • Manually reconfigure the Send handler for each the existing Static Send Port first, configuring them with the new or correct Send Handler;
  • and then manually delete the “BizTalkServerApplication” as a Send handler for each adapter;

You may have heard this before, but it never hurts, all of these tasks are time consuming, and a little boring to do after a while or if we need to do it several times;

So how can we automate tasks? and reuse them whenever necessary and at the same time saving significant time for other tasks?

Using PowerShell is a good option J. Windows PowerShell is a Windows command-line shell designed especially for system administrators and can be used by BizTalk administrators to help them in automating repetitive tasks or tasks that are time consuming to perform manually.

This is a simple script that allows you to configure the Send handler associated with all the existing Static Send Ports in your environment independently of the adapter that is configured:

$catalog = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
$catalog.ConnectionString = "SERVER=$bizTalkDbServer;DATABASE=$bizTalkDbName;Integrated Security=SSPI"

foreach($SendPort in $catalog.SendPorts)
{
    # For each receive location in your environment
    if($sendPort.IsDynamic -eq $False)
    {
        # Let's look for send handlers associated with Adapter configured in the send port
        foreach ($handler in $catalog.SendHandlers)
        {
            # if the Send Handler is associated with the Adapter configured in the send port
            if ($handler.TransportType.Name -eq $sendPort.PrimaryTransport.TransportType.Name)
            {
                # We will configured the port with the default send handler associated in each adapter in you system  
                # independently if it is "BizTalkServerApplication" or not.
                # Note: it's is recomended that you first configure the default send handlers for each adapter 
                #       and also not to use the "BizTalkServerApplication" (my personal recomendation)
                if($handler.IsDefault)
                { 
                    $sendPort.PrimaryTransport.SendHandler = $handler
                    break
                }
            }
        }
    }
}
$catalog.SaveChanges()

Prerequisites for this script: The host, host instances and Receive handlers needs to be already configured in your environment before you run the script;

THIS POWERSHELL IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.

The full script can be found and download on Microsoft TechNet Gallery:
PowerShell to Configure the Default Send Handler for each static Send Port (3.0 KB)
Microsoft TechNet Gallery

Following the topic from my previous post, when we are configuring/optimizing a new environment, if some features are installed like EDI features or RosettaNet Accelerator, if we create different or dedicated host and host instances for each functionality, for example a host instance for receive, send, process (orchestrations), tracking and so on; of course then we need to associate them as a specific handler of each adapter (receive or send handler) and if we want to delete the “BizTalkServerApplication” as a receive handler from each adapter… we can’t!

This happens because, at least, both EDI and RosettaNet will create during the installation some Receive Ports:

  • BatchControlMessageRecvPort with a receive location BatchControlMessageRecvLoc using SQL Adapter
  • ResendReceivePort with a receive location ResendReceiveLocation using SQL Adapter
  • LOB_To_PrivateInitiator with a receive location LOB_To_PrivateInitiator using SQL Adapter
  • LOB_To_PrivateResponder with a receive location LOB_To_PrivateResponder using SQL Adapter

And all these ports, by default during the installation, are configured with the only existing Receive handler available at the time: “BizTalkServerApplication”.

To accomplish the task of deleting “BizTalkServerApplication” as a receive handler of each adapter, we need to do basically the same steps described in my last post:

  • Manually reconfigure the Receive handler for each the existing receive location first, configuring them with the new Receive Handler;
  • and then manually delete the “BizTalkServerApplication” as a Receive handler for each adapter;

This task can be more normal to happen on the first time we configure/optimize the environment – day one of the BizTalk Server – but can be more critical if you reach to an existing environment, already containing several BizTalk Applications running, that is not configured according to best practices in terms of host and host instances.

Once again, all of these tasks are time consuming, and to be fair… again…, they are a little boring to do after we know how to do it manually;

So how can we automate tasks? and reuse them whenever necessary and at the same time saving significant time for other tasks?

Using PowerShell is a good option J. Windows PowerShell is a Windows command-line shell designed especially for system administrators and can be used by BizTalk administrators to help them in automating repetitive tasks or tasks that are time consuming to perform manually.

This is a simple script that allows you to configure the receive handlers associated with all the existing Receive Ports in your environment that are using the SQL Adapter, but this can be easily changed to cover all the Receive Locations independently of the configured adapter:

$catalog = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
$catalog.ConnectionString = "SERVER=$bizTalkDbServer;DATABASE=$bizTalkDbName;Integrated Security=SSPI"

foreach($receivePort in $catalog.ReceivePorts)
{
    # For each receive location in your environment
    foreach($recLocation in $receivePort.ReceiveLocations)
    {
        # In this case I want only Receive location that are using SQL Adapter
        if($recLocation.ReceiveHandler.TransportType.Name -eq 'SQL')
        {
            # Let's look for receive handlers associated with SQL Adapter
            foreach ($handler in $catalog.ReceiveHandlers)
            {
                # if is a SQL Adapter Receive Handler
                if ($handler.TransportType.Name -eq "SQL")
                {
                    # And is not BizTalkServerApplication, then configure that as the handler of the receive location
                    # Note: that in this case we will configure as a Receive Handler of the Receive location, the first 
                    #       receive handler that we find that is not the "BizTalkServerApplication"
                    #       because the goal is to delete this handler
                    if($handler.Name -ne 'BizTalkServerApplication')
                    { 
                        $recLocation.ReceiveHandler = $handler
                        break
                    }
                }
            }
        }
    }
}
$catalog.SaveChanges()

Prerequisites for this script: The host, host instances and Receive handlers needs to be already configured in your environment before you run the script;

THIS POWERSHELL IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.

The full script can be found and download on Microsoft TechNet Gallery:
PowerShell to Configure Receive Handlers from existing Receive locations (3.0 KB)
Microsoft TechNet Gallery

As happens almost every year on this day (my birthday), I always try to write a post for the BizTalk community… something like a gift/present to the community… today will be automate the task of configuring default Dynamic Send ports handlers using PowerShell.

Since BizTalk Server 2013 we have available a new feature: Configurable Dynamic Send Port Handler. Which means that, when we are creating a Dynamic Send Port, an adapter Send Handler can be configurable for every installed adapter, by default it uses the default send handler associated in each adapter. This Includes both One-Way and Solicit-Response Dynamic Ports.

Note that in previous BizTalk versions, a dynamic send port uses the adapter’s default host, and we cannot change this behavior.

However, this new features also brings us some setbacks, special for BizTalk Administrators, for example:

  • When we are installing a new environment, if we install the EDI features, this will add a dynamic port call “ResendPort” (don’t need to describe the propose of this port) and the default send handler for each adapter will be the “BizTalkServerApplication”;
    • If we create different or dedicated host and host instances for each functionality, for example a host instance for receive, send, process (orchestrations), tracking and so on; of course then we need to associate them as a specific handler of each adapter (receive or send handler) and if we want to delete the “BizTalkServerApplication” as a send handler for each adapter… we can’t, we first need to:
      • Manually reconfigure the default Dynamic Send port handlers for each dynamic port first, configuring them with the new default send handler;
      • and then manually delete the “BizTalkServerApplication” as a send handler for each adapter;
  • The same happens when we install a new adapter. By default, it assumes the default host in the group as the default send handler of the adapter and in consequence the default send handler associated with this adapter in the existing dynamic send ports. Which means that once again we need to manually reconfigure the send handler in all the existing dynamic send ports for this new adapter;
  • And so on;

All of these tasks are time consuming, and to be fair, they are a little boring to do after we know how to do it manually;

So how can we automate tasks? and reuse them whenever necessary and at the same time saving significant time for other tasks?

Using PowerShell is a good option. Windows PowerShell is a Windows command-line shell designed especially for system administrators and can be used by BizTalk administrators to help them in automating repetitive tasks or tasks that are time consuming to perform manually.

This is a simple script that allows you to configure the default send handlers associated with all the existing Dynamic Send ports in your environment:

[string] $sendHost32bits = "BizTalkServerSend32Host"
[string] $sendHost64bits = "BizTalkServerSendHost"

$catalog = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
$catalog.ConnectionString = "SERVER=$bizTalkDbServer;DATABASE=$bizTalkDbName;Integrated Security=SSPI"

foreach($sendPort in $catalog.SendPorts)
{
    if($sendPort.IsDynamic -eq' True')
    {
        # A Dynamic send port was found so now we need to configure the send handler as desired
        # 64 bits adapters
        # Changing the default send handlers of the dynamic port
        $sendPort.SetSendHandler("FILE", $sendHost64bits)
        $sendPort.SetSendHandler("HTTP", $sendHost64bits)
        $sendPort.SetSendHandler("MQSeries", $sendHost64bits)
        $sendPort.SetSendHandler("MSMQ", $sendHost64bits)
        $sendPort.SetSendHandler("SB-Messaging", $sendHost64bits)
        $sendPort.SetSendHandler("SFTP", $sendHost64bits)
        $sendPort.SetSendHandler("SOAP", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-BasicHttp", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-BasicHttpRelay", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-Custom", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-NetMsmq", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-NetNamedPipe", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-NetTcp", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-NetTcpRelay", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-SQL", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-WebHttp", $sendHost64bits)
        $sendPort.SetSendHandler("WCF-WSHttp", $sendHost64bits)
        $sendPort.SetSendHandler("Windows SharePoint Services", $sendHost64bits)       

        # 32 bits adapters
        # SMTP Supports 64 bits but I want to run in 32 because of the MIME/SMIME Encoder
        $sendPort.SetSendHandler("FTP", $sendHost32bits)
        $sendPort.SetSendHandler("SMTP", $sendHost32bits)
        $sendPort.SetSendHandler("SQL", $sendHost32bits)
    }
}

$catalog.SaveChanges() 

Prerequisites for this script: The host, host instances and send handlers needs to be already configured in your environment before you run the script;

THIS POWERSHELL IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.

The full script can be found and download on Microsoft TechNet Gallery:
PowerShell to configure Default Dynamic Send Port Handlers for each Adapter (3.0 KB)
Microsoft TechNet Gallery

Last Monday I presented my second session in the Integration Monday series (see my last post) and, as usually, I normally publish a post on my blog before the event – a way to help the organizers to advertise the event – or sometimes after the event sharing the resources… but I just now realized that I never created a post in my blog about my first session in the Integration Monday series: BizTalk Server Tips & Tricks for Developers and Admins (Deep Dive)

A session similar to the one I did in BizTalk Summit 2015 London event (also available online here) but a more open session addressing more tips and going into more detail – because I had more time, almost 82 minutes comparing to the 30 minutes I had in London Smile – and according to the Integration Monday organizers it has been a quite popular (or viewed) session.

Integration-Monday-organizers-tips-amd-tricks-feadback

So it is time to solve this "my big fault" and share with you the resources of this session – a session with a simple topic that I really love – I think that this (the topic) is the session that gave me more pleasure in making.

Sandro-Pereira-Integration-Monday-BizTalk-Server-Tips-Tricks-Developers-Admins-Deep-Dive

Session: BizTalk Server Tips & Tricks for Developers and Admins (Deep Dive)

Abstract: It’s critical to use good tools and techniques to produce working solutions as quickly as possible and at the same time, given the increase the requirements and number of applications organizations develop today. But at the same time, it’s also critical to maintain the health of the entire platform. In this session I’ll address and share some useful BizTalk Server Tips and Tricks (and Workarounds) both for developers and administrators that we can use in our daily work. And by doing so I’m hoping to simplify a little and/or automate some of the repeating tasks that we normally do and by sharing some unusual things or techniques that we can use I’m hoping to help you simplify your BizTalk solutions. Covering some topics like RosettaNet, SAP, database maintenance, debatching, out-of-the-box pipelines vs custom pipelines and many more

I hope you enjoy and find it an interesting session. Also I advise you to visit and view the sessions history that have taken place every Monday in the Integration User Group – Integration Monday series.

Have you had the time to think about what is some features like RosettaNet, ESB or UDDI have in common?

Well, all of them have custom databases and all of them are optional features.

But the most important question here, because they have custom databases, is: Do you think that these databases are being backedup? And the data inside are saved?

And the response is NO… Because these “custom” databases are not installed with BizTalk Server, they are not included in the default list of databases to be marked and backed up by the Backup BizTalk Server job. So if you want the Backup BizTalk Server job to back up RosettaNet, ESB or UDDI custom databases, you must manually add the databases to the Backup BizTalk Server job.

BizTalk-Server-Default-Database-backups

Fortunately for us, Microsoft provides two SQL Scripts:

  • Backup_Setup_All_Procs.sql
  • Backup_Setup_All_Tables.sql

That can be found in the Schema folder inside the BizTalk installation folder: “C:\Program Files (x86)\Microsoft BizTalk Server 2013 R2\Schema”, that you need to run against these databases in other to extend the standard backup mechanisms. However you also need to modify the adm_OtherBackupDatabases table (present in the BizTalk Management (BizTalkMgmtDb) database) to include a row for each these custom databases.

How to Back Up Custom Databases (RosettaNet, ESB or UDDI databases)

Note: I will not advise you to backup any custom application databases (database used to support BizTalk Application processes or others) with the Backup BizTalk Server job, with the exception of custom BizTalk database, like RosettaNet, UDDI or ESB.

To accomplish that you need to:

  • Browse to the “C:\Program Files (x86)\Microsoft BizTalk Server 2013 R2\Schema” directory, and then run against the RosettaNet, ESB or UDDI (custom) databases the following SQL scripts.
    • Backup_Setup_All_Procs.sql
    • and Backup_Setup_All_Tables.sql

BizTalk-Server-run-SQL-scripts-to-backup-custom-databases

  • So in this case we need to run these two SQL scripts against the following databases
    • RosettaNet
      • BTARNARCHIVE
      • BTARNCONFIG
      • BTARNDATA
    • ESB Toolkit
      • EsbExceptionDb
      • EsbItineraryDb
    • UDDI
      • UDDI3

Note: This creates the necessary procedures, table, and role and assigns permissions to the stored procedures.

  • Modify the adm_OtherBackupDatabases table, present in the in the BizTalk Management (BizTalkMgmtDb) database, to include a row for each of your custom databases
    • Type the new server and database names in the corresponding columns
      • DefaultDatabaseName: The friendly name of your custom database.
      • DatabaseName: The name of your custom database.
      • ServerName: The name of the computer running SQL Server.
      • BTSServerName: The name of the BizTalk Server. This value is not used, but it must contain a value nonetheless.

BizTalk-Server-adm_OtherBackupDatabases-table-configuration

The next time you run the Backup BizTalk Server job, it will back up your custom databases.

BizTalk-Server-with-custom-Database-backups

See this and more tips here: BizTalk Server Tips & Tricks for Developers and Admins (Deep Dive)

Probably this was one of the most talked and funny tips and I completely forgot to publish in my blog despite the resources despite the resources are already available for download and referenced in the session slides that you can found here.

If you are familiarly with the BizTalk Innovation Day or BizTalk Summit’s, you will all remember that at some point my dear friend Tord Glad Nordahl complaining in his session about BizTalk Developers writing unnecessary information in the Application Event Log and for they do not use the Event Viewer. You can also check his post and his point of view about this topic: BizTalk + Event log = angry admins

My goal here is not to criticize those who use the event viewer or if there is better way to accomplish this task (monitor/logging BizTalk applications errors)… but I partially have to agree with Tord and say that… you shouldn’t write custom application errors, warnings or information in the Application Event Log.

Many times BizTalk developers like to write information’s that will help them tracking and debugging there orchestrations like:

  • Message received
  • Message successfully Transformed
  • Message sent to external system

custom-source-logs-logged-application-event-log

And for that they normally use the following code:

System.Diagnostics.EventLog.WriteEntry("AnnoyingTord",
               "Just an update Tord! Message successfully Transformed");

The problem using this code is that by default these information is being logged in the Application Event Log. You need to realize that Application Event Log holds almost all the important information related to different aspects in BizTalk – SQL, IIS, BizTalk infrastructure and runtime problems – it is one of the main places that admins used to monitor “applications” installed in your server/machine. And these is the information that is extremely important for BizTalk Administrator in order to monitor the wellbeing of the platform and to diagnose problems and you don’t want to infest this event log with irrelevant and unnecessary information at the point to be almost impossible to find real problems – instead you, or in this case the admins, should keep it clean.

So I told – “I partially have to agree…” – because I think that this are unnecessary information that are being logged in the Application Event Log that doesn’t provide any additional information to BizTalk Administrators but…

But I told – “I partially have to agree…” – because, instead, you can use a custom event log for logging that unnecessary information that doesn’t provide any additional information to BizTalk Administrators and in this case I really don’t care if you are using the Event Viewer to log BizTalk application errors or tracking or debugging information (despite I don’t agree this last part).

So you can use the Event viewer as long as you do not use the Application Event Log to write custom errors.

Building the Sample

In this sample you will find a simple orchestration that will receive any XML message and will log some traditional tracking information that developers normally do in their orchestrations… I call this trying to annoying Tord Glad Nordahl (my friend and one of the best BizTalk Administrator that I know):

Trying-to-Annoying-Tord

The source code can be found and download on MSDN Code Gallery:
BizTalk Server: Moving Event Source To Different Event Log (Administration) (152.2 KB)
MSDN Code Gallery

 

What the Admin does normally?

When facing this type of development, BizTalk Administrators normally ask the developer’s to change their code, to not write in the application log or to disable this type of logging/tracking. Code that already is deployed in all the environments.

However change is hard – Getting others to change can be impossible or a big challenge – Developers will try to find a thousand excuses for explaining why such information is important!

What the Admin should do?

My advice:

• Let the developer by happy by writing in the Event Viewer

But take back the control of your environment by easily creating or using PowerShell

With this script you can easily move an Event Source to a different or to a Custom Windows Event Log:

foreach ($LogSource in $LogSources) {
    Remove-EventLog -Source $LogSource
} 

$logFileExists = Get-EventLog -list | Where-Object {$_.logdisplayname -eq $LogName}
if (! $logFileExists) {
    $LogSources | %{
        New-EventLog -LogName $LogName -Source $_
    } 

    # Compose Key:
    $LogPath = 'HKLM:\SYSTEM\CurrentControlSet\services\eventlog\'+$LogName;
    if(Test-Path $LogPath)
    {
        $acl = Get-Acl $LogPath
        $GpOrUsers | %{
            $ace = New-Object System.Security.AccessControl.RegistryAccessRule $_,'WriteKey, ReadKey','allow'
            $acl.AddAccessRule($ace)
            #Set-Acl $LogPath $acl
        }
    }else{Write-Error "Cannot acesss log $LogName"}
}
else {
    $LogSources | %{
        New-EventLog -LogName $LogName -Source $_
    }
}

moving-source-logs-to-another-event-log

This way, you as an admin can take back the control of your environment and fix the blunders (or foolishness) of the developers – if you are a BizTalk developer, don’t be offended please, I’m also a BizTalk Developer.

The script can be found and download on Microsoft TechNet Gallery:
BizTalk DevOps: Moving an Event Source To a Different/Custom Windows Event Log (4.2 KB)
Microsoft TechNet Gallery

 

Again If you are a developer and you for some reason want to write “tracking” or error information in the Event Viewer, then you should start to optimize your code to write by default in a custom Event log. You can use for example a similar code:

string logName = “MyCustomEventLog”;
string logName = “MyProjectLogSource”;

if (!System.Diagnostics.EventLog.SourceExists(logName))
{
   System.Diagnostics.EventLog.CreateEventSource(projectName, logName);
}
System.Diagnostics.EventLog.WriteEntry(projectName, genericString.ToString(), logType);

BizTalk is shipped out with a total of 13 SQL Agent jobs. Experienced BizTalk professionals know that all the BizTalk SQL Server Agent jobs except the MessageBox_Message_Cleanup_BizTalkMsgBoxDb job should be enabled and running successfully. Besides this job the other jobs should not be disabled!

However one of the most common and important tools to resolve problems that happens in BizTalk Server is the BizTalk Terminator tool (you can know more about this tool here). Terminator provides the easiest way to resolve most of these issues identified by the Monitor BizTalk Server Job.

Nevertheless, before running the Terminator tool, you must always make sure that:

  • you have a BizTalk Backup of your databases
  • all the BizTalk hosts instances have been stopped,
  • and all BizTalk SQL Agent jobs have been disabled.

Unfortunately, through SQL Server Management Studio console there is no easy way to disable or enable all jobs, forcing us to go one on one to disable or enable them.

disable-BizTalk-SQL-Server-Agent-jobs

This query will disable all the BizTalk SQL Server Agent jobs (including the MessageBox_Message_Cleanup_BizTalkMsgBoxDb):

update msdb.dbo.sysjobs set [enabled] = 0 where [name] = 'Backup BizTalk Server (BizTalkMgmtDb)'
update msdb.dbo.sysjobs set [enabled] = 0 where [name] = 'CleanupBTFExpiredEntriesJob_BizTalkMgmtDb'
update msdb.dbo.sysjobs set [enabled] = 0 where [name] = 'DTA Purge and Archive (BizTalkDTADb)'
...
update msdb.dbo.sysjobs set [enabled] = 0 where [name] = 'TrackedMessages_Copy_BizTalkMsgBoxDb'
update msdb.dbo.sysjobs set [enabled] = 0 where [name] = 'MessageBox_Message_Cleanup_BizTalkMsgBoxDb'

After all the task are complete we need of course to enable and start everything. This query will enable all the BizTalk SQL Server Agent jobs (with the exception of MessageBox_Message_Cleanup_BizTalkMsgBoxDb):

update msdb.dbo.sysjobs set [enabled] = 1 where [name] = 'Backup BizTalk Server (BizTalkMgmtDb)'
update msdb.dbo.sysjobs set [enabled] = 1 where [name] = 'CleanupBTFExpiredEntriesJob_BizTalkMgmtDb'
update msdb.dbo.sysjobs set [enabled] = 1 where [name] = 'DTA Purge and Archive (BizTalkDTADb)'
...
update msdb.dbo.sysjobs set [enabled] = 1 where [name] = 'TrackedMessages_Copy_BizTalkMsgBoxDb'

The SQL queries can be found and download on Microsoft TechNet Gallery:
SQL Query to Disable All BizTalk SQL Server Agent jobs
Microsoft TechNet Gallery

 

SQL Query to Enable All BizTalk SQL Server Agent jobs
Microsoft TechNet Gallery

Probably this will be the first post of a series about “How to take control of your environment”, especially how to take back the control of your environment from the mistakes of developers. And don’t get me wrong I am mainly a developer but I also play the role of the administrator and sometimes I also make mistakes… especially this one that I will talk about.

Who are careful to disable the tracking options for all the artifacts before publish the solution in production environment?

Well I sometimes forget to disable tracks event in orchestration: orchestration start and end, Message send and receive and Shape start and end; and sometimes we actually don’t need to track all this information, they will be there because someone forgot to disable it. Most important this information is only useful for orchestration debugger purpose when things are failing and we always can at any time turn it on for a specific application or orchestration, we don’t need that options active for all the applications.

What’s the implications of these settings being active in production?

“Document tracking can impact performance throughout BizTalk, not just Orchestration. For Orchestration, you should realize that Orchestration Event Tracking is on by default. This is useful during development and testing since Orchestration Events are required for Orchestration Debugger. However, if you do not intend to debug an Orchestration directly in production, you should turn Orchestration Event Tracking off. Orchestration Events are eventually moved to DTA_DEBUGTRACE table in BizTalkDTADB by TDDS. We have seen slow read/writes to this table once it gets large (several hundred thousand rows). What is considered large may vary due to your SQL Server hardware. In the end, if TDDS cannot move data efficiently into BizTalkDTADB, data is accumulated in BizTalkMsgBoxDB. Large MsgBoxDB can cause all of your hosts to slow down, and eventually lead to throttling.“ by Everett Yang (see: Thoughts on Orchestration Performance)

So as BizTalk Server processes more and more data on your system, the BizTalk Tracking (BizTalkDTADb) database may continue to grow in size that can causing poor disk performance.

Should I disable global tracking option?

By default, global tracking is enabled when you install BizTalk Server and if you are having performance issues in your environment that are momentarily addressed by purging the BizTalk tracking database, you may consider turning off global tracking, again momentarily, so that BizTalk stop collecting tracking information. You can accomplish that by modifying the group-level settings:

  • In the BizTalk Server Administration Console, expand BizTalk Server Administration, right-click BizTalk Group, and then click Settings.
  • In the BizTalk Settings Dashboard dialog box, on the Group page, do the following:
    • Disable “Enable group level tracking” option

BizTalk-Settings-Dashboard-Enable-group-level-tracking

However I advise you to do this only cases of emergency when you are having performance issues in production environment otherwise you should left this option enable at all time, why? Because turning off global tracking disables the tracking interceptors for the entire BizTalk Server group, which means, BizTalk Server will not track any events in its tracking tables. And sometimes we need to enable tracking for some artifacts.

So what’s the alternative?

The alternative is to configure for each application in each artifact: orchestrations, schemas, ports … the correct tracking settings. However this is a thankless and unpleasant task, because we have to go into all artifacts, especially in schemas, in order to configure them properly.

The first option to easily accomplish this task is to:

  • Go to the BizTalk Administration Console and Select “All Artifacts”
  • Select “Orchestrations” option and then select all the orchestrations available
  • Click “Tracking…” option in the right panel under “Selected Items” panel

BizTalk-Administration-Console-All-Artifacts-tracking

By configuring the tracking options this will apply for all the selected orchestrations with only one operation. This will works fine for all the artifacts… except schemas! Because in schemas you will need to go one by one.

The second option is using PowerShell script to accomplish this task, you could also do it with C# code but I think that PowerShell is a more familiar language for the administrators or sys admins.

How can I automate this task?

Windows PowerShell is a Windows command-line shell designed especially for system administrators and can be used by BizTalk administrators to help them in automating tasks.

This is a simple script to disable all tracking settings for all the artifacts in your BizTalk Server Environment:

# Disable tracking settings in orchestrations    
$Application.orchestrations | 
%{ $_.Tracking = [Microsoft.BizTalk.ExplorerOM.OrchestrationTrackingTypes]::None }

# Disable tracking settings in Send ports       
$disablePortsTracking = New-Object Microsoft.BizTalk.ExplorerOM.TrackingTypes
$Application.SendPorts | 
%{ $_.Tracking = $disablePortsTracking }

# Disable tracking settings in Receive ports
$Application.ReceivePorts | 
%{ $_.Tracking = $disablePortsTracking }

# Disable tracking settings in pipelines        
$Application.Pipelines | 
%{ $_.Tracking = [Microsoft.BizTalk.ExplorerOM.PipelineTrackingTypes]::None }

# Disable tracking settings in Schemas
$Application.schemas | 
	?{ $_ -ne $null } |
	?{ $_.type -eq "document" } |
	%{ $_.AlwaysTrackAllProperties = $false }

The script can be found and download on Microsoft TechNet Gallery:
BizTalk DevOps: How to Disable Tracking Settings in BizTalk Server Environment (5.7 kB)
Microsoft TechNet Gallery

Personally I like to create all my BizTalk Server installation and configuration process manually at least one time or maybe from time to time, but when we are dealing with several environments and even worse each environment with several BizTalk Servers… this can be very annoying and time consuming. In this case automation is the key!

One of the task that we need to do in all our new BizTalk environment over and over again is creating and configuring the Host, Host Instances and of course the adapter handlers.

What’s is Host, Host Instances and Adapter Handlers?

The BizTalk Host is a logical process and security boundary within BizTalk Server that represents a logical set of zero or more run-time processes in which you can deploy BizTalk Server services and artifacts (such as adapter handlers, receive locations, and orchestrations). Each host has a security group assigned to it and may contain multiple host instances, each on an individual machine, that perform the work of the host.

In turn, a host instance is the physical instance of a host on a computer running BizTalk Server. Each host instance belongs to exactly one host, and the service account of the host instance belongs to the security group of the host. The security group may be used to grant permissions to physical resources such as databases for use by any host instances in the host.

An adapter handler is an instance of a BizTalk host in which the adapter code runs. When you specify a send or receive handler for an adapter you are specifying which host instance the adapter code will run in the context of. An adapter handler is responsible for executing the adapter and contains properties for a specific instance of an adapter. A default BizTalk Server configuration will create adapter handlers for all of the installed adapters, but you may want to create additional adapter handlers for purposes of load balancing or to provide process isolation for a particular adapter handler.

Best practices to Configuring Hosts and Host Instances

As the official documentation specify, in addition to the high availability aspects of the host instance configuration, you should separate sending, receiving, processing, and tracking functionality into multiple hosts. This provides flexibility when configuring the workload in your BizTalk group and is the primary means of distributing processing across a BizTalk group.

This also allows you to stop one host without affecting other hosts. For example, you may want to stop sending messages to let them queue up in the MessageBox database, while still allowing the inbound receiving of messages to occur.

Separating host instances by functionality also provides some of the following benefits:

  • Each host instance has its own set of resources such as memory, handles, and threads in the .NET thread pool.
  • Multiple BizTalk Hosts will also reduce contention on the MessageBox database host queue tables since each host is assigned its own work queue tables in the MessageBox database.
  • Throttling is implemented in BizTalk Server at the host level. This allows you to set different throttling characteristics for each host.
  • Security is implemented at the host level; each host runs under a discrete Windows identity.

However this also may bring some potential drawbacks if too many host instances are created because each host instance is a Windows service (BTSNTSvc.exe or BTSNTSvc64.exe), which generates additional load against the MessageBox database and consumes computer resources (such as CPU, memory, threads), so you need to be careful.

Normally we read that we need to create at least 4 host instances: sending, receiving, processing, and tracking, but that’s not absolutely true because, at least with the newer environments, we typically use 64-bits versions and in this case we also need to create at least one Host Instance that will run on 32-bits because FTP adapter, SQL adapter, POP3 adapter and MIME Decoder on 64-bit host instances is not supported by the product (http://technet.microsoft.com/en-us/library/aa560166.aspx)

We can define that one of the best practices for hosts and host instances is the following:

  • BizTalkServerTrackingHost: A BizTalk Host that hosts tracking is responsible for moving the DTA and BAM tracking data from the MessageBox database to the BizTalk Tracking (DTA) and BAM Primary Import databases. This movement of tracking data has an impact on the performance of other BizTalk artifacts that are running in the same host that is hosting tracking. Thus, you should use a dedicated host that does nothing but host tracking.
    • Only the optionAllow Host Tracking” must be selected because we only will use this host for tracking.
  • BizTalkServerReceiveHost: All options (Allow Host Tracking”, “32-bits only” or “Make this default host in the group”) should be unselected. This host will be responsible for processing messages after they are picked up in a receive location. When a host contains a receiving item, such as a receive location (with a pipeline), the message decoding and decrypting occurs in a pipeline within this host.
    • All receive handlers, except the isolated ones like SOAP, HTTP, WCF-BasicHttp, WCF-WsHttp or WCF-CustomIsolated and 32 bit adapters (FTP,SQL and POP3) will be configured for this host. This will mean also that all receive locations will run in this host instance.
  • BizTalkServerReceive32Host: has the same goal as the previous however this must have the “32-bits only” option select so that we can run the 23-bits adapters.
    • The receive handlers for the FTP, SQL and POP3 adapters will be configured for this host.
  • BizTalkServerSendHost: All options (Allow Host Tracking”, “32-bits only” or “Make this default host in the group”) should be unselected. This host will be responsible for processing messages before they are sent out to the send port. When a host contains a sending item, such as a send port, the message signing and encryption occurs in a pipeline within this host.
    • All send handlers, except 32 bit adapters like native SQL and FTP adapter, will be configured for this host. This will mean also that all send ports will run in this host instance.
  • BizTalkServerSend32Host: has the same goal as the previous however this must have the “32-bits only” option select so that we can run the 32-bits adapters.
    • The Send handlers for the FTP and SQL adapters will be configured for this host.
  • BizTalkServerApplication: Only the option32-bits only” should be select in this host. This host will be responsible for process messages based on the instructions in orchestrations that need to run in 32-bits.
  • BizTalkServerApplication64Host: Only the optionMake this default host in the group” should be select in this host. This host will be responsible for process messages based on the instructions in all or most common orchestrations.

Note: You can create other Application Host if you want to separate process base in some application logic.

How can I automate this task?

Windows PowerShell is a Windows command-line shell designed especially for system administrators and can be used by BizTalk administrators to help them in automating tasks.

This is a simple script to configure the Host, Host Instance and Adapter Handlers described earlier in this post:
Function that will create a new BizTalk Host

function CreateBizTalkHost([string]$hostName, [int]$hostType, [string]$ntGroupName, [bool]$authTrusted, [bool]$isTrackingHost, [bool]$is32BitOnly)
{
    try
    {
        [System.Management.ManagementObject]$objHostSetting = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostSetting").CreateInstance()

        $objHostSetting["Name"] = $hostName
        $objHostSetting["HostType"] = $hostType
        $objHostSetting["NTGroupName"] = $ntGroupName
        $objHostSetting["AuthTrusted"] = $authTrusted
        $objHostSetting["IsHost32BitOnly"] = $is32BitOnly
        $objHostSetting["HostTracking"] = $isTrackingHost

        $putOptions = new-Object System.Management.PutOptions
        $putOptions.Type = [System.Management.PutType]::CreateOnly;

        [Type[]] $targetTypes = New-Object System.Type[] 1
        $targetTypes[0] = $putOptions.GetType()

        $sysMgmtAssemblyName = "System.Management"
        $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
        $objHostSettingType = $sysMgmtAssembly.GetType("System.Management.ManagementObject")

        [Reflection.MethodInfo] $methodInfo = $objHostSettingType.GetMethod("Put", $targetTypes)
        $methodInfo.Invoke($objHostSetting, $putOptions)

		Write-Host "Host $hostName was successfully created" -Fore DarkGreen
    }
    catch [System.Management.Automation.RuntimeException]
    {
		if ($_.Exception.Message.Contains("Another BizTalk Host with the same name already exists in the BizTalk group.") -eq $true)
        {
			Write-Host "$hostName can't be created because another BizTalk Host with the same name already exists in the BizTalk group." -Fore DarkRed
        }
		else{
        	write-Error "$hostName host could not be created: $_.Exception.ToString()"
		}
    }
}

Function that will update an existent BizTalk Host

function UpdateBizTalkHost([string]$hostName, [int]$hostType, [string]$ntGroupName, [bool]$authTrusted, [bool]$isTrackingHost, [bool]$is32BitOnly, [bool]$isDefaultHost)
{
    try
    {
        [System.Management.ManagementObject]$objHostSetting = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostSetting").CreateInstance()

        $objHostSetting["Name"] = $hostName
        $objHostSetting["HostType"] = $hostType
        $objHostSetting["NTGroupName"] = $ntGroupName
        $objHostSetting["AuthTrusted"] = $authTrusted
        $objHostSetting["IsHost32BitOnly"] = $is32BitOnly
        $objHostSetting["HostTracking"] = $isTrackingHost
		$objHostSetting["IsDefault"] = $isDefaultHost

        $putOptions = new-Object System.Management.PutOptions
        $putOptions.Type = [System.Management.PutType]::UpdateOnly; # This tells WMI it's an update.

        [Type[]] $targetTypes = New-Object System.Type[] 1
        $targetTypes[0] = $putOptions.GetType()

        $sysMgmtAssemblyName = "System.Management"
        $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
        $objHostSettingType = $sysMgmtAssembly.GetType("System.Management.ManagementObject")

        [Reflection.MethodInfo] $methodInfo = $objHostSettingType.GetMethod("Put", $targetTypes)
        $methodInfo.Invoke($objHostSetting, $putOptions)

		Write-Host "Host $hostName was successfully updated" -Fore DarkGreen
    }
    catch [System.Management.Automation.RuntimeException]
    {
        write-Error "$hostName host could not be updated: $_.Exception.ToString()"
    }
}

Function that will create a new BizTalk Host Instance

function CreateBizTalkHostInstance([string]$hostName, [string]$serverName, [string]$username, [string]$password)
{
    try
    {
        [System.Management.ManagementObject]$objServerHost = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_ServerHost").CreateInstance()

        $objServerHost["HostName"] = $hostName
        $objServerHost["ServerName"] = $serverName
        $objServerHost.Map()

        [System.Management.ManagementObject]$objHostInstance = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_HostInstance").CreateInstance()

        $name = "Microsoft BizTalk Server " + $hostName + " " + $serverName
        $objHostInstance["Name"] = $name
        $objHostInstance.Install($username, $password, $true)

		Write-Host "HostInstance $hostName was mapped and installed successfully. Mapping created between Host: $hostName and Server: $Server);" -Fore DarkGreen
    }
    catch [System.Management.Automation.RuntimeException]
    {
		if ($_.Exception.Message.Contains("Another object with the same key properties already exists.") -eq $true)
        {
			Write-Host "$hostName host instance can't be created because another object with the same key properties already exists." -Fore DarkRed
        }
		else{
        	write-Error "$hostName host instance on server $Server could not be created: $_.Exception.ToString()"
		}
    }
}

Function that will delete an existent host handlers in the adapters

function DeleteBizTalkAdapterHandler([string]$adapterName, [string]$direction, [string]$hostName)
{
	try
    {
		if($direction -eq 'Receive')
		{
			[System.Management.ManagementObject]$objHandler = get-wmiobject 'MSBTS_ReceiveHandler' -namespace 'root\MicrosoftBizTalkServer' -filter "HostName='$hostName' AND AdapterName='$adapterName'"
	        $objHandler.Delete()
		}
		else
		{
			[System.Management.ManagementObject]$objHandler = get-wmiobject 'MSBTS_SendHandler2' -namespace 'root\MicrosoftBizTalkServer' -filter "HostName='$hostName' AND AdapterName='$adapterName'"
	        $objHandler.Delete()
		}

		Write-Host "$direction handler for $adapterName / $hostName was successfully deleted" -Fore DarkGreen
    }
    catch [System.Management.Automation.RuntimeException]
    {
        if ($_.Exception.Message -eq "You cannot call a method on a null-valued expression.")
        {
			Write-Host "$adapterName $direction Handler for $hostName does not exist" -Fore DarkRed
        }
        elseif ($_.Exception.Message.IndexOf("Cannot delete a receive handler that is used by") -ne -1)
        {
			Write-Host "$adapterName $direction Handler for $hostName is in use and can't be deleted." -Fore DarkRed
        }
		elseif ($_.Exception.Message.IndexOf("Cannot delete a send handler that is used by") -ne -1)
        {
			Write-Host "$adapterName $direction Handler for $hostName is in use and can't be deleted." -Fore DarkRed
        }
		elseif ($_.Exception.Message.IndexOf("Cannot delete this object since at least one receive location is associated with it") -ne -1)
        {
			Write-Host "$adapterName $direction Handler for $hostName is in use by at least one receive location and can't be deleted." -Fore DarkRed
        }
        else
        {
            write-Error "$adapterName $direction Handler for $hostName could not be deleted: $_.Exception.ToString()"
        }
    }
}

Function that will create a handler for a specific adapter on the host

function CreateBizTalkAdapterHandler([string]$adapterName, [string]$direction, [string]$hostName, [string]$originalDefaulHostName, [boolean]$isDefaultHandler, [boolean]$removeOriginalHostInstance)
{
	if($direction -eq 'Receive')
	{
		[System.Management.ManagementObject]$objAdapterHandler = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_ReceiveHandler").CreateInstance()
		$objAdapterHandler["AdapterName"] = $adapterName
	    $objAdapterHandler["HostName"] = $hostName
	}
	else
	{
		[System.Management.ManagementObject]$objAdapterHandler = ([WmiClass]"root/MicrosoftBizTalkServer:MSBTS_SendHandler2").CreateInstance()
		$objAdapterHandler["AdapterName"] = $adapterName
	    $objAdapterHandler["HostName"] = $hostName
	    $objAdapterHandler["IsDefault"] = $isDefaultHandler
	}

    try
    {
        $putOptions = new-Object System.Management.PutOptions
        $putOptions.Type = [System.Management.PutType]::CreateOnly;

        [Type[]] $targetTypes = New-Object System.Type[] 1
        $targetTypes[0] = $putOptions.GetType()

        $sysMgmtAssemblyName = "System.Management"
        $sysMgmtAssembly = [System.Reflection.Assembly]::LoadWithPartialName($sysMgmtAssemblyName)
        $objAdapterHandlerType = $sysMgmtAssembly.GetType("System.Management.ManagementObject")

        [Reflection.MethodInfo] $methodInfo = $objAdapterHandlerType.GetMethod("Put", $targetTypes)
        $methodInfo.Invoke($objAdapterHandler, $putOptions)

        Write-Host "$adapterName $direction Handler for $hostName was successfully created" -Fore DarkGreen
    }
    catch [System.Management.Automation.RuntimeException]
    {
		if ($_.Exception.Message.Contains("The specified BizTalk Host is already a receive handler for this adapter.") -eq $true)
        {
			Write-Host "$hostName is already a $direction Handler for $adapterName adapter." -Fore DarkRed
        }
		elseif($_.Exception.Message.Contains("The specified BizTalk Host is already a send handler for this adapter.") -eq $true)
        {
			Write-Host "$hostName is already a $direction Handler for $adapterName adapter." -Fore DarkRed
        }
		else {
        	write-Error "$adapterName $direction Handler for $hostName could not be created: $_.Exception.ToString()"
		}
    }

	if($removeOriginalHostInstance)
	{
		DeleteBizTalkAdapterHandler $adapterName $direction $originalDefaulHostName
	}
}

Function that will have the logic you want to implement to create the default hosts and host instances and add configure the host instances to the various handlers

function ConfiguringBizTalkServerHostAndHostInstances
{
	# Separate sending, receiving, processing, and tracking functionality into multiple hosts.
	# This provides flexibility when configuring the workload and enables you to stop one host without affecting other hosts.
	# you can use a common well use convention to define the name of the host:
	#  - <Job>_<bit support>_<seq>_<adapter/functionality>_<throughput>_<priority>_<clustered>
	# Sample 'Rcv_x32_1_FTP_L_Critical_Clustered'
	# But I will use a more simple convencion
	# Defining the names of the hosts
	[string]$receiveHostName = 'BizTalkServerReceiveHost'
	[string]$sendHostName = 'BizTalkServerSendHost'
	[string]$processingHostName = 'BizTalkServerApplication64Host' # use this to create another processing host
	[string]$trackingHostName = 'BizTalkServerTrackingHost'
	# Note: why we need to create 32bits hosts? FTP, POP3 and SQL doesn't support 64bits
	[string]$receive32HostName = 'BizTalkServerReceive32Host'
	[string]$send32HostName = 'BizTalkServerSend32Host'

	# 'BizTalkServerApplication' is the default host instance created when you install the biztalk on your box.
	# This application will be running on "32-bit only".
	[string]$defaultHostName = 'BizTalkServerApplication'

 	##############################
	# Creating hosts for receiving
	# HostType: Invalid: 0, In-process:	1, Isolated: 2
	CreateBizTalkHost $receiveHostName 1 $ntHostGroupName $false $false $false
	CreateBizTalkHost $receive32HostName 1 $ntHostGroupName $false $false $true

	# Create a host instances for receiving associated with the previous hosts created
	CreateBizTalkHostInstance $receiveHostName $bizTalkServerName $hostCredentials.UserName $hostCredentialsPassword
	CreateBizTalkHostInstance $receive32HostName $bizTalkServerName $hostCredentials.UserName $hostCredentialsPassword

	# Set adapters that should be handled by receiving host instance
	CreateBizTalkAdapterHandler 'FILE' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'MQSeries' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'MSMQ' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-Custom' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-NetMsmq' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-NetNamedPipe' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-NetTcp' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'Windows SharePoint Services' 'Receive' $receiveHostName $defaultHostName $false $removeOriginalAdapterHandler
	#32 bits adapters
	CreateBizTalkAdapterHandler 'FTP' 'Receive' $receive32HostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'POP3' 'Receive' $receive32HostName $defaultHostName $false $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'SQL' 'Receive' $receive32HostName $defaultHostName $false $removeOriginalAdapterHandler

 	##############################
	# Creating hosts for sending
	# HostType: Invalid: 0, In-process:	1, Isolated: 2
	CreateBizTalkHost $sendHostName 1 $ntHostGroupName $false $false $false
	CreateBizTalkHost $send32HostName 1 $ntHostGroupName $false $false $true

	# Create a host instances for sending associated with the previous hosts created
	CreateBizTalkHostInstance $sendHostName $bizTalkServerName $hostCredentials.UserName $hostCredentialsPassword
	CreateBizTalkHostInstance $send32HostName $bizTalkServerName $hostCredentials.UserName $hostCredentialsPassword

	# Set adapters that should be handled by sending host instance
	CreateBizTalkAdapterHandler 'FILE' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'HTTP' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'MQSeries' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'MSMQ' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'SOAP' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'SMTP' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-BasicHttp' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-Custom' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-NetMsmq' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-NetNamedPipe' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-NetTcp' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'WCF-WSHttp' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'Windows SharePoint Services' 'Send' $sendHostName $defaultHostName $true $removeOriginalAdapterHandler
	#32 bits adapters
	CreateBizTalkAdapterHandler 'FTP' 'Send' $send32HostName $defaultHostName $true $removeOriginalAdapterHandler
	CreateBizTalkAdapterHandler 'SQL' 'Send' $send32HostName $defaultHostName $true $removeOriginalAdapterHandler

	# Create a host for tracking
	CreateBizTalkHost $trackingHostName 1 $ntHostGroupName $false $true $false

	# Create a host for orchestrations
	CreateBizTalkHost $processingHostName 1 $ntHostGroupName $false $false $false

	# Create a host instance for orchestrations
	CreateBizTalkHostInstance $processingHostName $bizTalkServerName $hostCredentials.UserName $hostCredentialsPassword

	# Create a host instance for tracking
	CreateBizTalkHostInstance $trackingHostName $bizTalkServerName $hostCredentials.UserName $hostCredentialsPassword

	# Remove "Allow Host Tracking" options from BizTalkServerApplication Host
	UpdateBizTalkHost $defaultHostName 1 $ntHostGroupName $false $false $true $true

	# Updating the processinh host to be the default host
	UpdateBizTalkHost $processingHostName 1 $ntHostGroupName $false $false $false $true
}

And in the last the main script

Write-Host "Starting configure the BizTalk Server environment..." -Fore DarkGreen

# General variables
# Defining the BizTalk Server Name, this line will read the Server name on which the script is running
$bizTalkServerName = $(Get-WmiObject Win32_Computersystem).name

# STEP 1
# The Windows group is used to control access of a specif host and associated host instances to databases and other
# resources. Each instance of this host must run under a user account that is a member of this group.
# Note that you can change the Windows group only if no instances of this host exist.
# Defining the name of the group the BizTalk hosts should run under
[string]$ntHostGroupName = Read-Host -Prompt "Please enter windows group to control access to Hosts and ssociated Host Instances"

# STEP 2
# This account must have SQL Server permissions. The recommended way to grant these permissions is to add this account
# to the BizTalk Server Host Windows group.
# BizTalk Server will add this account to the "Log on as a service" security policy.
# For domain accounts, use "domain\user" format
# Defining the credentials in witch the host instance should run under.
try
{
	$domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
	$domainName = $domain.name
}
catch
{
	$domainName = $(Get-WmiObject Win32_Computersystem).name
}
$hostCredentials = $Host.ui.PromptForCredential("Logon Credentials","This account must have SQL Server permissions. The recommended way to grant these permissions is to add this account to the BizTalk Server Host Windows group.

BizTalk Server will add this account to the 'Log on as a service' security policy", $domainName + "\", "");
[String]$hostCredentialsPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($hostCredentials.Password));

# STEP 3
# Defining the option if you want to automatically try to remove the BizTalkServerApplication Host Instance from
# the Adapters handlers
$windowsShell = new-object -comobject wscript.shell
$questionResult = $windowsShell.popup("Do you want to try to remove the BizTalkServerApplication Host Instance from the Adapters handlers?

Note: The script cannot remove the default host instances if there are any receiveports, sendports or orchestrations configured.",
						  0,"BizTalk Applications, Receive and Send Ports",4)

If ($questionResult -eq 6) {
	$removeOriginalAdapterHandler = $true
}
else {
	$removeOriginalAdapterHandler = $false
}

# STEP 4
# Create default hosts, host instances and handlers
Write-Host "Creating hosts and host instances..." -Fore DarkGreen
ConfiguringBizTalkServerHostAndHostInstances

# STEP 5
# This configurations changes requires host instances restart for the changes to take effect.
# Check if you want to restart the Host Instances
Write-Host "Host and Host Instance configuration is almost completed..." -Fore DarkGreen
$questionResult = $windowsShell.popup("This configurations changes requires host instances restart for the changes to take effect.

Do you want to restart the Host Instances now?", 0,"Please restart Host Instances",4)
If ($questionResult -eq 6) {
	get-service BTS* | foreach-object -process {restart-service $_.Name}
	Write-Host "Restart Host Instance completed..." -Fore DarkGreen
}

# STEP 6
# Check if you want to properly configure BizTalk Services and Enterprise Single Sign-On Service 'Startup type' property
# to Automatic (Delayed Start)
$questionResult = $windowsShell.popup("By default, the 'Startup type' propriety of BizTalk Services and Enterprise Single Sign-On Service are set as 'Automatic', however BizTalk Server services may not start automatically after a system restart, to avoid this behavior you must config the 'Startup type' to 'Automatic (Delayed Start)'.

Do you want to configure BizTalk Services to 'Automatic (Delayed Start)'?", 0,"Configure BizTalk Services to Automatic (Delayed Start)",4)
If ($questionResult -eq 6) {
	#=== Name of the Enterprise Single Sign-On Service. ===#
	$entSSOServiceName = 'ENTSSO'

	#=== Change the startup type for BizTalk services to Automatic (Delayed Start) ===#
	get-service BTSSvc* | foreach-object -process { SC.EXE config $_.Name start= delayed-auto}

	#=== Change the startup type for Enterprise Single Sign-On Service to Automatic (Delayed Start) ===#
	SC.EXE config $entSSOServiceName start= delayed-auto

	Write-Host "BizTalk Services and SSO configured successfully..." -Fore DarkGreen
}

Write-Host "Your BizTalk Server environment is now properly configured" -Fore DarkGreen

The script can be found and download on Microsoft TechNet Gallery:
PowerShell to Configure BizTalk Server Host and Host Instances (7.4 KB)
Microsoft TechNet Gallery