Introduction

Maintaining a good and healthy BizTalk environment is important, to ensure maximum performance and avoid unexpected issues and unplanned downtime. A BizTalk health check contains several checklist items, and a full check should be performed by a 3rd party at least once a year. This article will explain and discuss the contents of the PowerShell script available in TechNet Gallery.

How To Use

  • Download BizTalkHealthCheck.ps1 from TechNet Gallery
  • Copy the file to the BizTalk environment you want to check. You have to be member of the BizTalk Server Administrators group
  • Run the script in Admin PowerShell console. Make sure PowerShell is not restricted

Details

To see what a BizTalk Health Check may look like, please see this page. A full health check may take 1 to 3 days, depending on the size of the environment and how detailed the health check is. This script will typically complete in a couple of minutes. There are several other tools available on the Internet, which can provide a lot of details about a BizTalk environment. Some of these are used in a "manual" health check. This script is intended to provide a quick health check without using other tools, and without performing any installations or PowerShell modules.

The script contains several items, as described in more detail in the following section. If you are only interested in parts of the script, feel free to use them in your own scripts for troubleshooting and other scenarios. This is also a good way to learn more about PowerShell. Note that the example results below are from a newly installed environment.

Health Check Items

The script will check the following items, divided in to 4 sections:

  1. BizTalk Information
  2. Windows Information
  3. Computer Information
  4. Network Information

BizTalk Information

General details

Details about the BizTalk environment, including version, server names, AD groups and global tracking.

try { # Get BizTalk Information
    $BizTalkGroup = Get-WmiObject MSBTS_GroupSetting -namespace root\MicrosoftBizTalkServer -ErrorAction Stop
    $BizTalkMsgBoxDb = Get-WmiObject MSBTS_MsgBoxSetting -namespace root\MicrosoftBizTalkServer -ErrorAction Stop
    $BizTalkServer = Get-WmiObject MSBTS_Server -namespace root\MicrosoftBizTalkServer -ErrorAction Stop
    $BizTalkREG = Get-ItemProperty "hklm:\SOFTWARE\Microsoft\BizTalk Server\3.0" -ErrorAction Stop
    $hostInstances = Get-WmiObject MSBTS_HostInstance -namespace root\MicrosoftBizTalkServer -ErrorAction Stop
    $trackingHost = Get-WmiObject MSBTS_Host -Namespace root\MicrosoftBizTalkServer -ErrorAction Stop | where {$_.HostTracking -eq "true" }
    [void] [System.reflection.Assembly]::LoadWithPartialName("Microsoft.BizTalk.ExplorerOM")
    $BizTalkDBInstance = $BizTalkGroup.MgmtDbServerName
    $BizTalkDB = $BizTalkGroup.MgmtDbName
    $BizTalkOM = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $BizTalkOM.ConnectionString = "SERVER=$BizTalkDBInstance;DATABASE=$BizTalkDB;Integrated Security=SSPI"
}
catch {
    Write-Host "BizTalk not detected on this machine, or user not member of BizTalk Administrators group" -fore Red
    exit
}
 
# Display BizTalk Information
Write-Host "`nBizTalk Information" -fore Green
Write-Host $BiztalkREG.ProductName "("$BiztalkREG.ProductEdition"Edition )"
Write-Host "Product Version:" $BiztalkREG.ProductVersion
Write-Host "Installation Path:" $BiztalkREG.InstallPath
Write-Host "Installation Date:" $BiztalkREG.InstallDate
Write-Host "Server name:" $BiztalkServer.Name
Write-Host "SSO Server:" $BizTalkGroup.SSOServerName
Write-Host "BizTalk Admin group:" $BizTalkGroup.BizTalkAdministratorGroup
Write-Host "BizTalk Operators group:" $BizTalkGroup.BizTalkOperatorGroup
Write-Host "BizTalk Group Name:" $BizTalkGroup.Name
Write-Host "Cache Refresh Interval:" $BizTalkGroup.ConfigurationCacheRefreshInterval
 
switch ($BizTalkGroup.GlobalTrackingOption) {
    0 { Write-Host "Global Tracking: Off" }
    1 { Write-Host "Global Tracking: On" }
}

Example result



Installed BizTalk software

List of installed related software

Write-Host "`nInstalled BizTalk Software" -Fore DarkGray
Get-WmiObject win32_product | where-object { $_.Name -like "*BizTalk*" } | select-object Name -Unique | Sort-Object Name | select -expand Name

Example result



Host instance information

Host instance name, type and status.

# Display BizTalk Host Instance Information
Write-Host "`nHost Instance Information ("$hostInstances.Count")" -fore DarkGray
 
foreach ($hostInstance in $hostInstances) {
    switch ($hostInstance.servicestate) {
        1 { $hostInstanceState = "Stopped" }
        2 { $hostInstanceState = "Start pending" }
        3 { $hostInstanceState = "Stop pending" }
        4 { $hostInstanceState = "Running" }
        5 { $hostInstanceState = "Continue pending" }
        6 { $hostInstanceState = "Pause pending" }
        7 { $hostInstanceState = "Paused" }
        8 { $hostInstanceState = "Unknown" }
    }
    switch ($hostInstance.HostType) {
        1 { $hostInstanceType = "In-process" }
        2 { $hostInstanceType = "Isolated" }
    }
    if ($hostInstanceState -eq "Running") {
        Write-Host $hostInstance.hostname "($hostInstanceType)" "- "  -NoNewline
        Write-Host $hostInstanceState -fore green
    }
    elseif ($hostInstanceState -eq "Stopped") {
            if ($hostInstance.IsDisabled -eq $true ) {
                Write-Host $hostInstance.hostname "($hostInstanceType)" "- " -NoNewline
                Write-Host $hostInstanceState "(Disabled)" -fore red
            }
            else {
                Write-Host $hostInstance.hostname "($hostInstanceType)" "- " -NoNewline
                Write-Host $hostInstanceState -fore Red
            }
    }
    else {
        if ($hostInstanceType -eq "In-process") {
            Write-Host $hostInstance.hostname "($hostInstanceType)" "- " -NoNewline
            Write-Host $hostInstanceState "(Disabled:$($hostInstance.IsDisabled))" -fore DarkYellow
        }
        else {
            Write-Host $hostInstance.hostname "($hostInstanceType)"
        }
    }
}
Write-Host "`nTracking Host(s)" -Fore DarkGray
$trackingHost.Name

Example result



BizTalk applications

BizTalk application count, name and status

# Get BizTalk Application Information
$applications = $BizTalkOM.Applications
 
# Display BizTalk Application Information
Write-Host "`nBizTalk Applications ("$applications.Count")" -fore DarkGray
 
Foreach ($application in $applications) {
    if ($application.Status -eq "Started") {
        Write-Host $application.Name "- " -NoNewline
        Write-Host $application.Status -fore Green
    }
    elseif ($application.Status -eq "Stopped") {
        Write-Host $application.Name "- " -NoNewline
        Write-Host $application.Status -fore Red
    }
    else {
        Write-Host $application.Name "- " -NoNewline
        Write-Host $application.Status -fore DarkYellow
    }
}

Example result



Service instance information

Instances ready to run, active, dehydrated, suspended, failures etc.

# Get BizTalk Service Instance Information
[ARRAY]$readyToRun = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceStatus = 1)' -ErrorAction SilentlyContinue
[ARRAY]$active = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceStatus = 2) and not(ServiceClass = 16)' -ErrorAction SilentlyContinue
[ARRAY]$dehydrated = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceStatus = 8)' -ErrorAction SilentlyContinue
[ARRAY]$breakpoint = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceStatus = 64)' -ErrorAction SilentlyContinue
[ARRAY]$suspendedOrchs = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceClass = 1) and (ServiceStatus = 4 or ServiceStatus = 32)' -ErrorAction SilentlyContinue
[ARRAY]$suspendedMessages = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceClass = 4) and (ServiceStatus = 4 or ServiceStatus = 32)' -ErrorAction SilentlyContinue
[ARRAY]$suspendedRouting = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceClass = 64)' -ErrorAction SilentlyContinue
[ARRAY]$suspendedIsolated = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceClass = 32) and (ServiceStatus = 4 or ServiceStatus = 32)' -ErrorAction SilentlyContinue
 
# Display BizTalk Service Instance Information
Write-Host "`nService Instance Information" -fore DarkGray
Write-Host "Instances Ready to Run:" $readyToRun.Count
Write-Host "Active Instances:" $active.Count
Write-Host "Dehydrated Instances:" $dehydrated.Count
Write-Host "Instances in Breakpoint:" $breakpoint.Count
Write-Host "Suspended Orchestrations:" $suspendedOrchs.count
Write-Host "Suspended Messages:" $suspendedMessages.count
Write-Host "Routing Failures:" $suspendedRouting.count
Write-Host "Isolated Adapter Failures:" $suspendedIsolated.count

Example result



Disabled and stopped artifacts

Disabled/Stopped/Unenlisted receive locations, send ports and orchestrations.

# Get and Display BizTalk Receive Location Information
[ARRAY]$recLocs = get-wmiobject MSBTS_ReceiveLocation -namespace 'root\MicrosoftBizTalkServer' | Where-Object {$_.IsDisabled -eq "true" }
Write-Host "`nDisabled Receive Locations (" $recLocs.Count ")" -fore DarkGray
 
if ($recLocs.Count -gt 0) { $recLocs.Name }
else { Write-Host "None" }
 
# Get and Display BizTalk Send Port Information
[ARRAY]$sendPorts = get-wmiobject MSBTS_SendPort -namespace 'root\MicrosoftBizTalkServer' | Where-Object {$_.Status -eq 2 -or $_.Status -eq 1}
Write-Host "`nStopped and Unenlisted Send Ports (" $sendPorts.Count ")" -fore DarkGray
 
if ($sendPorts.Count -gt 0) { $sendPorts.Name }
else { Write-Host "None" }
 
# Get and Display Orchstrations not started
[ARRAY]$orchs = Get-WmiObject MSBTS_Orchestration -namespace 'root\MicrosoftBizTalkServer' | Where-Object {$_.OrchestrationStatus -ne 4 }
Write-Host "`nNot Started Orchestrations (" $orchs.Count ")" -fore DarkGray
 
if ($orchs.Count -gt 0) { $orchs.Name }
else { Write-Host "None" }

Example result



Tracking information

Artifacts with tracking enabled.

# Tracking
Write-Host "`nTracking" -fore DarkGray
[ARRAY]$trackingSendPorts = get-wmiobject MSBTS_SendPort -namespace 'root\MicrosoftBizTalkServer' | Where-Object {$_.Tracking -gt 0 }
[ARRAY]$trackingRecPorts = get-wmiobject MSBTS_ReceivePort -namespace 'root\MicrosoftBizTalkServer' | Where-Object {$_.Tracking -gt 0 }
Write-Host "Receive Ports with Tracking:" $trackingRecPorts.Count
Write-Host "Send Ports with Tracking:" $trackingSendPorts.Count

Example result



Windows Information

General details

Windows details, version, architecture, page file, TEMP folders.

# Get and Display Windows Information
Write-Host "`nWindows Information" -fore Green
$windowsDetails = Get-WmiObject -Class Win32_OperatingSystem
Write-Host $windowsDetails.Caption
Write-Host "Product Version:" $windowsDetails.Version
Write-Host "Service Pack Level:" $windowsDetails.CSDVersion
$UpdateSession = New-Object -Com Microsoft.Update.Session
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
$SearchResult = $UpdateSearcher.Search("IsInstalled=0 and Type='Software'")
Write-Host "Missing Windows Updates:" $SearchResult.Updates.Count
Write-Host "Architecture:" $windowsDetails.OSArchitecture
Write-Host "Installation Path:" $windowsDetails.WindowsDirectory
Write-Host "Page File:" (Get-WmiObject Win32_PageFileUsage).Name
Write-Host "TEMP Folder:" $env:TEMP "("(Get-ChildItem $env:TEMP -File -Recurse | Measure-Object).count" file(s) )"
Write-Host "TMP Folder:" $env:TMP "("(Get-ChildItem $env:TMP -File -Recurse | Measure-Object).count" file(s) )"
if (Test-Path C:\temp) {
    Write-Host "C:\Temp:" (Get-ChildItem C:\temp -File -Recurse | Measure-Object).Count "file(s)"
}

Example result



Installed roles and features

Installed Windows roles and features. This will only work on servers.

Import-Module ServerManager
Get-WindowsFeature | Where-Object {$_.Installed -eq $True} | Sort-Object DisplayName | ft @{Expression={$_.DisplayName};Label="Installed Windows Roles and Features"}

Example result




IIS information

IIS version, application pool name, state and applications.

# Display IIS information
try {
    Import-Module WebAdministration
    Write-Host "IIS Version:" (get-itemproperty HKLM:\SOFTWARE\Microsoft\InetStp\).setupstring
    Write-Host "`nApplication Pools" -Fore DarkGray -NoNewLine
    Get-ChildItem IIS:\apppools | ft -AutoSize
}
catch {
    Write-Host "Unable to perform IIS checks" -fore Red
}

Example result



Windows services

Checks for unnecessary (server) services.

# Check Windows Service state
function FuncCheckService{
     param($ServiceName)
         $arrService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
         if ($arrService.Status -eq "Running"){
            Write-Host $ServiceName "is running"
            $script:unnecessaryServices++
         }
}
Write-Host("Unnecessary Windows Services") -Fore DarkGray
[int]$script:unnecessaryServices = 0
FuncCheckService("Print Spooler")
FuncCheckService("Alerter")
FuncCheckService("ClipBook")
FuncCheckService("DHCP Server")
FuncCheckService("Fax Service")
FuncCheckService("File Replication")
FuncCheckService("Infrared Monitor")
FuncCheckService("Internet Connection Sharing")
FuncCheckService("Messenger")
FuncCheckService("NetMeeting Remote Desktop Sharing")
FuncCheckService("Network DDE")
FuncCheckService("Network DDE DSDM")
FuncCheckService("NWLink NetBIOS")
FuncCheckService("NWLink IPX/SP")
FuncCheckService("Telephony")
FuncCheckService("Telnet")
FuncCheckService("Uninterruptible Power Supply")
if ($unnecessaryServices -eq 0) { Write-Host "None" }

Example result



MSDTC settings

Local MSDTC settings.

# Display MSDTC Information
Write-Host "`nMSDTC Settings" -Fore DarkGray
Write-Host "RemoteClientAccessEnabled:" (Get-DtcNetworkSetting -DtcName Local).RemoteClientAccessEnabled
Write-Host "RemoteAdministrationAccessEnabled:" (Get-DtcNetworkSetting -DtcName Local).RemoteAdministrationAccessEnabled
Write-Host "InboundTransactionsEnabled:" (Get-DtcNetworkSetting -DtcName Local).InboundTransactionsEnabled
Write-Host "OutboundTransactionsEnabled:" (Get-DtcNetworkSetting -DtcName Local).OutboundTransactionsEnabled
Write-Host "Authentication:" (Get-DtcNetworkSetting -DtcName Local).AuthenticationLevel
Write-Host "XATransactionsEnabled:" (Get-DtcNetworkSetting -DtcName Local).XATransactionsEnabled
Write-Host "LUTransactionsEnabled:" (Get-DtcNetworkSetting -DtcName Local).LUTransactionsEnabled

Example result



Windows Firewall status

Windows Firewall status.

# Display Windows Firewall Information
Write-Host "`nWindows Firewall Status" -fore DarkGray -NoNewLine
Get-NetFirewallProfile | Select-Object Name,Enabled | ft -AutoSize

Example result


Event log issues

First most common event log errors, then BizTalk related.

# Get and Display Application Event Log Information
Write-Host "Most Common Application Event Log Errors" -Fore DarkGray -NoNewLine
$eventLog = Get-EventLog -Log Application -EntryType Error
$eventLog | Group-Object -Property Source -NoElement | Sort-Object -Property Count -Desc | ft  -AutoSize
 
Write-Host "BizTalk Related Application Event Log Errors" -Fore DarkGray -NoNewLine
$BizTalkEventLog = Get-Eventlog -Log Application -EntryType Error | Where-Object {$_.eventID -eq "5410" -or $_.Source -like "*BizTalk*" -or $_.Source -like "*BAM*" -or $_.Source -like "*DTC*" -or $_.Source -like "*RuleEngine*"} | Select-Object Source,EventID,Message -Unique | Sort-Object Message | ft -AutoSize
$BizTalkEventLog

Example result



Computer Information

General details

File system, disk capacity and type, fragmentation, RAM, domain, computer model and manufacturer, BIOS details.

# Get and Display Computer Information
Write-Host "Computer Information" -fore Green
$computerDetails = Get-WmiObject Win32_ComputerSystem
$drive = Get-WmiObject -Class Win32_Volume -Filter "DriveLetter = 'C:'"
$defragReport = $drive.DefragAnalysis()
Write-Host "File System (C:):" $drive.FileSystem
Write-Host "Capacity (C:):" ([Math]::Round(($drive.Capacity / 1024 / 1024 / 1024),0)) "GB"
Write-Host "Fragmentation (C:):" $defragReport.DefragAnalysis.FilePercentFragmentation"%"
Write-Host "Free Disk Space (C:):" $defragReport.DefragAnalysis.FreeSpacePercent"%"
 
Write-Host "System Type:" $computerDetails.SystemType
Write-Host "Physical RAM:" ([math]::round(($computerDetails.TotalPhysicalMemory/1GB),0))"GB"
Write-Host "Domain:" $computerDetails.Domain
Write-Host "Computer Model:" $computerDetails.model
Write-Host "Computer Manufacturer:" $computerDetails.manufacturer
Write-Host "BIOS Version:" (Get-WmiObject Win32_BIOS).BIOSVersion
Write-Host "BIOS Serial Number:" (Get-WmiObject Win32_BIOS).serialnumber

Example result



CPU load

CPU/Core load.

$processors = Get-WmiObject win32_processor
if (@($processors)[0].NumberOfCores) { $cores = @($processors).count * @($processors)[0].NumberOfCores }
else { $cores = @($processors).count }
$sockets = @(@($processors) | % {$_.SocketDesignation} | select-object -unique).count;
     
Write-Host "`nProcessor(s) and Load Percentage" -Fore DarkGray
foreach ($processor in $processors ) { Write-Host $processor.Name "("$processor.LoadPercentage"% )" }
Write-Host "Cores: $cores, Sockets: $sockets"

Example result



Anti-virus and security software

Installed anti-virus and security software.

Write-Host("`nAnti-virus and Security Software") -Fore DarkGray
$antiVirus = Get-WmiObject Win32_Product -Filter "name LIKE '%virus%' or name LIKE '%defend%' or name LIKE '%security%' or name LIKE '%protect%'"
if ($antiVirus.Count -gt 0) { $antiVirus.Name }
else { Write-Host "None" }

Example result



Network Information

General details

TCP ports, connections, IP address, DHCP, gateway, MAC address, NetBIOS.

# Display Network Information
Write-Host "`nNetwork Information" -fore Green
Write-Host "TCP ports in use:" (netstat -ano -p tcp).Count
Write-Host "`nNetwork Connections" -fore DarkGray -NoNewLine
Get-NetAdapter | Select-Object Name,Status,LinkSpeed | ft  -AutoSize
 
$nics = Get-WmiObject -computer localhost win32_networkadapterconfiguration -Filter "ipenabled='true'"
Write-Host "IP Address(es):"
$nics.IPAddress
 
foreach ($nic in $nics ) {
    Write-Host "Description:" $nic.Description
    Write-Host "DHCP Server:" $nic.DHCPServer
    Write-Host "Default Gateway:" $nic.DefaultIPGateway
    Write-Host "MAC Address:" $nic.MACAddress
    Write-Host "NetBIOS over TCP/IP: " -NoNewline
    switch ($nic.TcpipNetbiosOptions) {
        0 { Write-Host "Enabled via DHCP" }
        1 { Write-Host "Enabled" }
        2 { Write-Host "Disabled" }
    }
}

Example result



Internet download speed test

Download time and speed for a 100MB file from http://speedtest.newark.linode.com.

Write-Host "`nInternet Download Test" -fore DarkGray
try {
    # Source download URL
     
    # Destination download file
    $destination = $env:USERPROFILE + "\Downloads\Download.txt"
 
    # Download file
    $startDownloadTime = Get-Date
    Invoke-WebRequest $source -OutFile $destination -ErrorAction Stop
    $endDownloadTime = Get-Date
     
    $fileSize = ([Math]::Round(((Get-Item $destination).Length / 1024),0))
    $totalTime = ([Math]::Round($(($endDownloadTime-$startDownloadTime).TotalSeconds), 2))
    Write-Host "Download Time: $totalTime seconds"
    Write-Host "File Size: $fileSize KB"
    Write-Host "Download Speed:" ([Math]::Round(($fileSize / $totalTime), 2)) "KB/s"
 
    # Delete downloaded file
    Remove-Item $destination
}
catch {
    Write-Host "Unable to perform Internet download speed test" -fore Red
}

Example result



Domain controller time sync

Domain controller time sync.

Write-Host "`nDomain Controller Time Sync" -fore DarkGray
try {
    Import-Module ActiveDirectory
    $DC = Get-ADDomainController -Discover -ErrorAction Stop | select -Expand HostName
    $TimeServer = w32tm /stripchart /computer:$DC /samples:5 /dataonly
    $TimeServer
}
catch {
    Write-Host "Unable to contact Domain Controller" -fore Red
}

Example result



Note that a SQL Server section is currently missing. To get any such useful information using PowerShell, a separate module is required (SQLPSX). This script is supposed to run without adding any other software or modules. A separate script containing SQL details may be released separately in the future.

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.