Introduction

When there is planned maintenance in BizTalk or related services, it is advisable to stop BizTalk services in a controlled fashion. There are two scenarios which are slightly different

  1. You are planning to upgrade BizTalk Server itself, for instance, installing a Cumulative Update or using BizTalk Terminator
  2. There is planned downtime in your infrastructure which affects BizTalk, for instance SQL Server reboot
If BizTalk is not stopped in a controlled fashion, you can experience suspended messages, timeouts, event log errors and worse (especially in scenario 1). To avoid this, disable receive locations, let processing complete, stop host instances, Windows Services and the SQL Agent Service. The two latter depends on which scenario it applies.

All of this can be automated using PowerShell, and is downloadable from here.

Details

The TechNet Gallery download contains three scripts:

  • FullStopBizTalk.ps1 - for scenario 1, and will:
    1. Disable receive locations
    2. Wait 10 minutes, let processing complete (configurable timeout)
    3. Stop host instances
    4. Stop related Windows Services
    5. Stop SQL Agent Service
  • StopBizTalk.ps1 - for scenario 2, and will:
    1. Disable receive locations
    2. Wait 10 minutes, let processing complete (configurable timeout)
    3. Stop host instances
    4. Stop IIS service
  • StartBizTalk.ps1 - for both scenarios (after maintenance), and will:
    1. Start related Windows Services
    2. Enable host instances
    3. Start SQL Server Agent
    4. Enable receive locations

Code

Below is the PowerShell code for FullStopBizTalk.ps1. StopBizTalk.ps1 basically does the same, but with fewer steps (see details above). StartBizTalk.ps1 is also very similar to the code below, it's just starting services and doing steps in a different order.

The code contains lots of comments, and should be easy to read and understand.

<#
.SYNOPSIS
Stop BizTalk Server in a controlled fashion
.DESCRIPTION
This script disables all receive locations, waits 10 minutes (configurable), stops host instances, Windows Services and the SQL Agent Service.
.PARAMETER computers
Array of BizTalk servers. Without parameters it will use localhost. Computers must be in same BizTalk group (e.g. PROD)
.EXAMPLE
.\FullStopBizTalk.ps1
.EXAMPLE
.\FullStopBizTalk.ps1 -computers "biztalkserver1","biztalkserver2"
.NOTES
You need to be member of local admin and BizTalk Server Administrators group to run this script.
#>
[cmdletbinding()]
param(
    [Parameter(HelpMessage="Comma separated list of BizTalk servers")]
    [ARRAY]$computers
)
cls
# If no parameters, use localhost
if ($computers.Count -eq 0) {
    $computers += @("localhost")
}
 
try { # Disable receive locations
    Write-Host "Disabling Receive Locations..." -fore Green
 
    # Get all enabled BizTalk receieve locations
    $recLocs = Get-WmiObject msbts_receivelocation -ComputerName $computers[0] -Namespace 'root\MicrosoftBizTalkServer' -ErrorAction Stop | Where-Object { $_.IsDisabled -eq $false }
 
    # Disable them
    $recLocs.Disable() | Out-Null
    Write-Host "All receive locations are now disabled"
}
catch { # Unable to disable receive locations
    Write-Host $_.Exception.Message -fore Red
}
 
# Wait - let processing complete
$waitTime = 600 # seconds
Write-Host "`nWaiting $([Math]::Round(($waitTime/60),1)) minute(s) before proceeding..." -fore green
try {
    $timeout = New-TimeSpan -Seconds $waitTime
    $sw = [diagnostics.stopwatch]::StartNew()
    while ($sw.Elapsed -lt $timeout) { # Display progress bar while waiting
        $percComplete = (($sw.ElapsedMilliseconds/10)/$waitTime)
        $timeRemaining = ($waitTime-($sw.ElapsedMilliseconds/1000))
        Write-Progress -Activity "Waiting $([Math]::Round(($waitTime/60),1)) minute(s) before stopping Host Instances, Windows Services and SQL Agent Service" -PercentComplete $percComplete -Status "Please wait" -SecondsRemaining $timeRemaining -ErrorAction Stop
        Start-Sleep -Seconds 1
    }
}
catch { # Unable to show progress bar
    Write-Host $_.Exception.Message -fore Red
    Start-Sleep -Seconds $waitTime
}
finally {
    Write-Host "Waiting time over"
}
 
try { # Disable host instances
    Write-Host "`nDisabling Host Instances..." -fore Green
 
    # Get all BizTalk host instances
    $hostInstances = Get-WmiObject MSBTS_HostInstance -ComputerName $computers[0] -Namespace 'root\MicrosoftBizTalkServer' -ErrorAction Stop
    foreach ($hostInstance in $hostInstances ) { # Stop all in-processs host intances which are not already stopped
        if (($hostInstance.HostType -eq 1 ) -and ($hostInstance.ServiceState -ne 1)) { $hostInstance.Stop() | Out-Null }
    }
    Write-Host "All host instances are now disabled"
}
catch { # Unable to disable host instances
    Write-Host $_.Exception.Message -fore Red
}
 
try { # Stop Windows services
    Write-Host "`nStopping Windows Services..." -fore Green
     
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'Enterprise Single Sign-On Service' | Stop-Service -Force }
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'IIS Admin Service' | Stop-Service -Force }
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'World Wide Web Publishing Service' | Stop-Service -Force }
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'Distributed Transaction Coordinator' | Stop-Service -Force }
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'Rule Engine Update Service' | Stop-Service -Force }
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'IP Helper' | Stop-Service -Force }
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'User Access Logging Service' | Stop-Service -Force }
    $computers | foreach { Get-Service -ComputerName $computers -DisplayName 'Windows Management Instrumentation' | Stop-Service -Force }
     
    Write-Host "Windows services are now stopped"
}
catch { # Unable to stop Windows service(s)
    Write-Host $_.Exception.Message -fore Red
}
 
try { # Stop SQL Agent Service
    Write-Host "`nStopping SQL Agent Service..." -fore Green
 
    # Get SQL database server
    $BizTalkDB = Get-WmiObject MSBTS_GroupSetting -namespace root\MicrosoftBizTalkServer -ErrorAction Stop | Select -ExpandProperty MgmtDbServerName
 
    if ($BizTalkDB.Contains("\")) { # Named instance
        $backslashPos = $BizTalkDB.IndexOf("\")
        $DBserver = $BizTalkDB.Substring(0, $backslashPos)
        $DBinstance = $BizTalkDB.Substring($backslashPos+1)
        Get-Service -DisplayName "SQL Server Agent ($DBinstance)" -ComputerName $DBserver -ErrorAction Stop | Stop-Service
    }
    else { # Default instance
        Get-Service -DisplayName 'SQL Server Agent (MSSQLSERVER)' -ComputerName $BizTalkDB  -ErrorAction Stop | Stop-Service
    }
    Write-Host "SQL Agent Service is now stopped"
}
catch { # Unable to stop SQL Agent Service
    Write-Host $_.Exception.Message -fore Red
}

Instructions

Download the ZIP-file from the gallery, copy to your BizTalk server and unzip. Run the scripts manually or use Windows Task Scheduler. Remember to run as administrator. There is one optional parameter ($computers). You can provide a list of BizTalk servers. The script will identify the SQL Server instance automatically. If the parameter is empty, localhost will be used. No modules or add-ins required.

Figure 1. Example how this can be configured in Windows Task Scheduler

Example 1

This will stop BizTalk artifacts, and then IIS on the local machine:

.\StopBizTalk.ps1

Example 2

This will stop BizTalk artifacts, and then IIS on two machines:

.\StopBizTalk.ps1 -computers "biztalkserver1","biztalkserver2"

Example 3

This will stop BizTalk artifacts, Windows Services and SQL Agent Service on one machine:

.\FullStopBizTalk.ps1 "biztalkserver1"

Example 4

This will start BizTalk artifacts, Windows Services and SQL Agent Service on the local machine:

.\StartBizTalk.ps1

Requirements

  • No modules or add-ins required
  • Windows PowerShell 3.0 or newer
  • Run script as administrator
  • User must be local admin and member of BizTalk Administrators group

See Also

Another important place to find an extensive amount of BizTalk related articles is the TechNet Wiki itself. The best entry point is BizTalk Server Resources on the TechNet Wiki.