BizTalk Server: Automating BizTalk to Stop Before a Planned Maintenance
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
- You are planning to upgrade BizTalk Server itself, for instance, installing a Cumulative Update or using BizTalk Terminator
- 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:
- Disable receive locations
- Wait 10 minutes, let processing complete (configurable timeout)
- Stop host instances
- Stop related Windows Services
- Stop SQL Agent Service
- StopBizTalk.ps1 - for scenario 2, and will:
- Disable receive locations
- Wait 10 minutes, let processing complete (configurable timeout)
- Stop host instances
- Stop IIS service
- StartBizTalk.ps1 - for both scenarios (after maintenance), and will:
- Start related Windows Services
- Enable host instances
- Start SQL Server Agent
- 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.