Introduction

One of the principal needs for BizTalk Administrators is the ability to monitor the health of BizTalk environments and react promptly to possible problems, you can accomplished this by using certain tools such as:

  • BizTalk Administration Console: is a Microsoft Management Console (MMC) that you can use to manage and monitor BizTalk Server, and that you can use to deploy and manage your BizTalk Server applications.
  • BizTalk360: that provides a nice user friendly interface to monitoring and supporting your BizTalk environments
  • SCOM (System Center Operation Manager) that can provide comprehensive monitoring for Windows systems and with the additional of BizTalk Server 2010 Management Pack, SCOM can offer also monitoring capabilities for BizTalk artifacts and BizTalk-related platform components.
  • And many more...

However, unfortunately many times, some of these tools are not available for us but we still need to accomplish this task. In these cases we can use PowerShell to accomplish these tasks.

Windows PowerShell is a Windows command-line shell designed especially for system administrators. It includes an interactive prompt and a scripting environment that can be used independently or in combination. PowerShell can be used by BizTalk administrators to help them in automating tasks and monitor certain resources or operations.

Using PowerShell To monitor BizTalk environments

Note: These type of scripts must be viewed as a complement to the tools mentioned above or used in the absence of them.

Disk Space Monitoring

Disk space is a common problem in all the server machines, BizTalk Server is not an exception. Admins should be aware and be notify if the servers are running out of space. With this script you can be able to configure disk free space warning and critical levels and monitoring disk spaces in your environment (BizTalk/SQL/Other machines) using PowerShell. If a threshold is reached an e-mail will be send.

#########################################################
# List of computers to be monitored
#########################################################
param (
      $serverList =  "C:\\Machine.txt"
)
$computers = Get-Content $serverList
 
#########################################################
# Configuration of alarmists
#########################################################
[decimal]$warningThresholdSpace = 20 # Percentage of free disk space - Warning (orange).
[decimal]$criticalThresholdSpace = 10 # Percentage of free disk space - critical (red)
 
#########################################################
# Monitoring Process
#########################################################
[System.Array]$results = foreach ($cmp in $computers) {
 Get-WMIObject  -ComputerName $cmp Win32_LogicalDisk |
where{($_.DriveType -eq 3) -and (($_.freespace/$_.size*100) -lt $warningThresholdSpace) }|
select @{n='Server Name' ;e={"{0:n0}" -f ($cmp)}},
@{n='Volume Name' ;e={"{0:n0}" -f ($_.volumename)}},
@{n='Driver' ;e={"{0:n0}" -f ($_.name)}},
@{n='Capacity (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},
@{n='Free Space (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}},
@{n='Percentage Free';e={"{0:n2}%" -f ($_.freespace/$_.size*100)}}
}

You can obtain the full script and read more about this atMonitor your BizTalk environment using PowerShell – Disk Space Monitoring

SQL Agent Jobs Monitoring

With this script you can be able to monitoring SQL Agent Jobs in your BizTalk environment using PowerShell. BizTalk is shipped out with a total of 12 SQL Agent jobs. 2 of these jobs must be configured. The two jobs that needs configuration are the two most important jobs. The “Backup BizTalk Server” and the “DTA Purge and Archive”. If any inconsistency are found an e-mail will be send.

#########################################################
# List of SQL Servers to be monitored
#########################################################
$sqlservers = Get-Content ".\SQL.txt";
 
#########################################################
# List of SQL Job that will not be subject to monitoring
#########################################################
$jobsToIgnore=@{
    "DTA Purge and Archive (BizTalkDTADb)" = "IGNORE"
}
 
#########################################################
# Monitoring Process
#########################################################
$report = foreach($sqlserver in $sqlservers) {
    # Create an SMO Server object
    $srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" $sqlserver;  # srv vai ficar com o nome do servidor na lista sqlservers
    # total jobs and start the counters to 0.
    $totalJobCount = $srv.JobServer.Jobs.Count;
    $failedCount = 0;
    $successCount = 0;
    $Day = Get-Date ;
  
    $tmp = foreach($job in $srv.JobServer.Jobs)
    {
        $colour = "Green";
        $jobName = $job.Name;
        $jobEnabled = $job.IsEnabled;
        $jobLastRunOutcome = $job.LastRunOutcome;
        $jobLastRunDate= $job.LastRunDate;
        $detail = $job.EnumHistory();
        $timerows = $job.EnumHistory().Rows
  
        [string]$runDetails=""
        if($job.EnumHistory().Rows[0] -ne $null){
            [string]$runDetails=""+ $job.EnumHistory().Rows[0].Message
            if($job.EnumHistory().Rows[1] -ne $null){
                [string]$runDetails+="<br><br>"+ $job.EnumHistory().Rows[1].Message
            }
        }
        else{
            [string]$runDetails="-"
        }
  
        $executions = foreach ($row in $timerows) {
            if(-not $row.HasErrors){
                New-Object PSObject -Property @{Duration = $row.RunDuratio}
            }
        }
  
        $media =  $executions | Measure-Object -Property Duration -Average | select -expand Average
        if($timerows -ne $null) {
            $lastRun =  $timerows[0]['RunDuration']
        }
        else
        {
            $lastRun = -1
        }
  
        if($jobLastRunOutcome -eq "Failed")
        {
            #$colour = "Red";
            $failedCount += 1;
        }
        elseif ($jobLastRunOutcome -eq "Succeeded")
        {
            $successCount += 1;
        }
        New-Object PSObject -Property @{
            Server = $sqlserver
            JobName = $jobName
            Enabled = $jobEnabled
            OK = $successCount
            Failed = $failedCount
            LastRun = $jobLastRunOutcome
            StartTime = $jobLastRunDate
            Duration = $lastRun
            ExpectedDuration = $media
            RunDetails=$runDetails
        }
  
        ##############################################################
        # Convert Seconds to Hours:Minutes:Seconds Table Duration    #
        ##############################################################
        if ($lastRun -gt 9999) {
            $hh = [int][Math]::Truncate($lastRun/10000);
            $lastRun = $lastRun - ($hh*10000)
        }
        else {
            $hh = 0
        }
        if ($lastRun -gt 99) {
            $mm = [int][Math]::Truncate($lastRun/100);
            $lastRun = $lastRun - ($mm*100)
        }
        else {
            $mm = 0
        }
        $dur = ("{0:D2}" -f $hh) + ':' + "{0:D2}" -f $mm + ':' + "{0:D2}" -f $lastRun
  
        ######################################################################
        # Convert Seconds to Hours:Minutes:Seconds Table ExpectedDuration    #
        ######################################################################
        [system.Double] $media
        [Int32] $imedia = [System.Convert]::ToInt32($media);
  
        if ($imedia -gt 9999) {
            $h = [System.Double][Math]::Truncate($imedia/10000);
            $imedia = $imedia - ($h*10000)
        }
        else {
            $h = 0
        }
        if ($imedia -gt 99) {
            $m = [System.Double][Math]::Truncate($media/100);
            $imedia = $imedia - ($m*100)
        }
        else {
            $m = 0
        }
        $expDura = ("{0:D2}" -f $h) + ':' + "{0:D2}" -f $m + ':' + "{0:D2}" -f $imedia
    }
}

Although I found the last script useful, I found three additional situations that are important to monitor:

  • Some of the jobs were disable
  • MessageBox_Message_Cleanup_BizTalkMsgBoxDb was enable
  • SQL Server Agent was running, BizTalk Jobs were correctly enable… but despite all that no job was running (the last execution has been 7 days back – coinciding with an intervention in the system)
So we need to modify the PowerShell script to accomplish these situations. With this script you can be able to monitoring SQL Agent Jobs in your BizTalk environment using PowerShell, checking:
  • If the jobs are being executed according to the schedulers that are configured
  • If all jobs (with the exception of MessageBox_Message_Cleanup_BizTalkMsgBoxDb) are enable
  • If MessageBox_Message_Cleanup_BizTalkMsgBoxDb is disable
WITH MostRecentSched AS
 (
 -- For each job get the most recent scheduled run date (this will be the one where Rnk=1)
 SELECT job_id,
        last_executed_step_date,
        RANK() OVER (PARTITION BY job_id ORDER BY last_executed_step_date DESC) AS Rnk
 FROM sysjobactivity
 )
 select name [Job Name],
    last_executed_step_date [Last Scheduled Run Date],
        DATEDIFF(minute, last_executed_step_date, SYSDATETIME()) AS [Minutes Delayed],
        CASE WHEN enabled=1 THEN 'Enabled'
          ELSE 'Disabled'
        END [Job Status]
from MostRecentSched MRS
JOIN   sysjobs SJ
ON     MRS.job_id=SJ.job_id
where Rnk=1
and ((
        ((name = 'Backup BizTalk Server (BizTalkMgmtDb)' and DATEDIFF(minute, last_executed_step_date, SYSDATETIME()) > 17))
        OR (name = 'CleanupBTFExpiredEntriesJob_BizTalkMgmtDb' and DATEDIFF(minute, last_executed_step_date, SYSDATETIME()) > 722)
        OR (name = 'Monitor BizTalk Server (BizTalkMgmtDb)' and DATEDIFF(minute, last_executed_step_date, SYSDATETIME()) > 11520)
        OR (name = 'Rules_Database_Cleanup_BizTalkRuleEngineDb' and DATEDIFF(minute, last_executed_step_date, SYSDATETIME()) > 62)
        OR (name = 'MessageBox_UpdateStats_BizTalkMsgBoxDb' and DATEDIFF(minute, last_executed_step_date, SYSDATETIME()) > 7)
        OR (name IN ('DTA Purge and Archive (BizTalkDTADb)','MessageBox_DeadProcesses_Cleanup_BizTalkMsgBoxDb', 'MessageBox_Parts_Cleanup_BizTalkMsgBoxDb', 'Operations_OperateOnInstances_OnMaster_BizTalkMsgBoxDb', 'PurgeSubscriptionsJob_BizTalkMsgBoxDb', 'TrackedMessages_Copy_BizTalkMsgBoxDb') and DATEDIFF(minute, last_executed_step_date, SYSDATETIME()) > 1)
    ) OR (name IN ('Backup BizTalk Server (BizTalkMgmtDb)','CleanupBTFExpiredEntriesJob_BizTalkMgmtDb',
                   'DTA Purge and Archive (BizTalkDTADb)', 'MessageBox_DeadProcesses_Cleanup_BizTalkMsgBoxDb',
                   'MessageBox_Message_ManageRefCountLog_BizTalkMsgBoxDb', 'MessageBox_Parts_Cleanup_BizTalkMsgBoxDb',
                   'MessageBox_UpdateStats_BizTalkMsgBoxDb', 'Monitor BizTalk Server (BizTalkMgmtDb)',
                   'Operations_OperateOnInstances_OnMaster_BizTalkMsgBoxDb',
                   'PurgeSubscriptionsJob_BizTalkMsgBoxDb', 'Rules_Database_Cleanup_BizTalkRuleEngineDb',
                   'TrackedMessages_Copy_BizTalkMsgBoxDb') AND SJ.enabled = 0)
      OR (name = 'MessageBox_Message_Cleanup_BizTalkMsgBoxDb' AND SJ.enabled = 1)
    )
order by name, last_executed_step_date desc;

You can obtain the full scripts and read more about them at:

Suspended instance monitoring

If you don’t have the proper tools you need to manually check if there is any suspended instances. Of course this is not a good solution and it is a time consuming task. With this script you can monitor BizTalk for suspended messages. If the script finds any suspended messages a mail will be sent.

#Get DB info
[STRING]$SQLInstance = get-wmiobject MSBTS_GroupSetting -namespace root\MicrosoftBizTalkServer | select-object -expand MgmtDbServerName
[STRING]$BizTalkManagementDb = get-wmiobject MSBTS_GroupSetting -namespace root\MicrosoftBizTalkServer | select-object -expand MgmtDbName
[STRING]$BizTalkGroup = "$SQLInstance" + ":" + "$BizTalkManagementDb"
 
#Get suspended messages
[ARRAY]$suspendedMessages = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceStatus = 4 or ServiceStatus = 16 or ServiceStatus = 32 or ServiceStatus = 64)'
 
#Cancel if there are no suspended messages
if ($suspendedMessages -eq $null) {exit}
 
#Create mail content
$mailBody += "<P>There are "+ $suspendedMessages.Count  + " suspended messages in the BizTalk group " + $BizTalkGroup + ".`n`n</P>"
[STRING]$Subject = $SubjectPrefix + $BizTalkGroup

You can obtain the full script and read more about this at: Monitor your BizTalk environment using PowerShell – Suspended instance monitoring

Old dehydrated instance monitoring

Sometimes you also need to know if you have any old dehydrated instances. Dehydrated instances aren't always errors, but in some BizTalk implementations it is an indication that something is wrong. With this script you can look for 'old' (you can configure what old means) dehydrated instances. If any are found an e-mail will be send.

#Get the current date
$Currentdate = get-date
 
#Get all dehydrated service instances
[ARRAY]$DehydratedServiceInstances = get-wmiobject MSBTS_ServiceInstance -namespace 'root\MicrosoftBizTalkServer' -filter '(ServiceStatus = 8)'
 
if ($DehydratedServiceInstances -ne $null)
{
    foreach ($DehydratedServiceInstance in $DehydratedServiceInstances)
    {
        #Get the part of the time string that is needed to convert the string to a date
        $StrActTime = $DehydratedServiceInstance.ActivationTime.Substring(0,14)
 
        $template = 'yyyyMMddHHmmss'
        #Convert the string to date
        $DateActTime = [DateTime]::ParseExact($StrActTime, $template, $null)
 
        #Increase the variable $NumberOfOldeDehydratedServiceInstances by one each time a dehydrated service instance is older then the number in $AlertHours
        If ($DateActTime -le $Currentdate.AddHours(-$AlertHours))
        {
            $NumberOfOldeDehydratedServiceInstances ++
        }
    }
}
 
#Create mail content
if ($NumberOfOldeDehydratedServiceInstances -eq 1)
{
    $mailBody += "<P>There is "+ $NumberOfOldeDehydratedServiceInstances + " dehydrated instance older then " + $AlertHours +  " hours in the BizTalk group " + $BizTalkGroup + ".`n`n</P>"
}
elseif ($NumberOfOldeDehydratedServiceInstances -gt 1)
{
    $mailBody += "<P>There are "+ $NumberOfOldeDehydratedServiceInstances + " dehydrated instances older then " + $AlertHours +  " hours in the BizTalk group " + $BizTalkGroup + ".`n`n</P>"
}

You can obtain the full script and read more about this atMonitor your BizTalk environment using PowerShell – Old dehydrated instance monitoring

Monitoring Stopped Ports

Monitoring if all the receive and send ports are up and running is a common task, normally admins monitor this manually which again is not a good solution and it is a time consuming task. With this script you can monitor and generate alerts by sending an e-mail if a send or receive port is down.

[BOOL]$Continuescript = $False
[BOOL]$StoppedSendPort = $False
[BOOL]$StoppedReceiveLocation = $False
 
 
#Get DB info
[STRING]$SQLInstance = get-wmiobject MSBTS_GroupSetting -namespace root\MicrosoftBizTalkServer | select-object -expand MgmtDbServerName
[STRING]$BizTalkManagementDb = get-wmiobject MSBTS_GroupSetting -namespace root\MicrosoftBizTalkServer | select-object -expand MgmtDbName
[STRING]$BizTalkGroup = "$SQLInstance" + ":" + "$BizTalkManagementDb"
 
#Get Send ports
[ARRAY]$SendPorts = get-wmiobject MSBTS_SendPort -namespace 'root\MicrosoftBizTalkServer'
 
#Get Receive locations
[ARRAY]$ReceiveLocations = get-wmiobject MSBTS_ReceiveLocation -namespace 'root\MicrosoftBizTalkServer'
 
Foreach ($SendPort in $SendPorts)
{
    write-host $SendPort.name " + " $SendPort.Status
}
 
Foreach ($ReceiveLocation in $ReceiveLocations)
{
    write-host $ReceiveLocation.name " + " $ReceiveLocation.IsDisabled
}
 
#Exit the script if there are no disabled receive locations and stopped/unelisted send ports
Foreach ($SendPort in $SendPorts)
{
    if ($sendports.count -ne (get-wmiobject MSBTS_SendPort -namespace 'root\MicrosoftBizTalkServer' -filter '(Status = 3)').count)
    {
        [BOOL]$script:Continuescript = $True
    }
}
Foreach ($ReceiveLocation in $ReceiveLocations)
{
    if ($ReceiveLocations.count -ne (get-wmiobject MSBTS_ReceiveLocation -namespace 'root\MicrosoftBizTalkServer' -filter '(IsDisabled = False)').count)
        {
           [BOOL]$script:Continuescript = $True
        }
}  
If ($Continuescript -eq $False)
{
    exit
}
 
#Create mail content
$mailBody += "<P>There are stopped send ports and/or disabled receive locations in the BizTalk group " + $BizTalkGroup + ".`n`n</P>"
[STRING]$Subject = $SubjectPrefix + $BizTalkGroup
$mailBody += "<P>Stopped send ports</P> `n`n"
 
#Add mail content for stopped send ports
Foreach ($SendPort in $SendPorts)
{
    #only add stopped send ports to the mail
    if ($SendPort.status -eq 2 -OR $SendPort.status -eq 1)
    {
        $StoppedSendPort = $True
        #Set status to a user friendly name
        if ($SendPort.status -eq 2)
        {
            $SendPortStatus = "Stopped"
        }
        elseif ($SendPort.status -eq 1)
        {
            $SendPortStatus = "Unelisted"
        }
     
        #Add mail content
        $mailBody += "<th><b>" + $SendPort.name + "</b></th>"
        $mailBody += "<table border=1>"
         
        $mailBody += "<TR><TD>Status</TD>"
        $mailBody += "<TD>" + $SendPortStatus + "</TD></TR>"
         
        $mailBody += "<TR><TD>URI</TD>"
        $mailBody += "<TD>" + $SendPort.PTAddress + "</TD></TR>"
         
        $mailBody += "<TR><TD>Transport type</TD>"
        $mailBody += "<TD>" + $SendPort.PTTransportType + "</TD></TR>"
 
        $mailBody += "</table>"
        $mailBody += "<BR><BR>"
    }
}
     
if ($StoppedSendPort -eq $False)
{
    $mailBody += "<P>There are no stopped send ports</P><BR><BR>"
}
 
$mailBody += "Receive locations `n`n"
 
#Add mail content for stopped receive locations
Foreach ($ReceiveLocation in $ReceiveLocations)
{
    #only add stopped receive locations to the mail
    if ($ReceiveLocation.IsDisabled -eq "True")
    {
        $StoppedReceiveLocation = $True
         
        #Set status to a user friendly name
        if ($ReceiveLocation.IsDisabled -eq "True")
        {
            $ReceiveLocationStatus = "Disabled"
        }
        elseif ($SendPort.IsDisabled -eq "False")
        {
            $ReceiveLocationStatus = "Enabled"
        }
         
        #Add mail content
        $mailBody += "<th><b>" + $ReceiveLocation.name + "</b></th>"
        $mailBody += "<table border=1>"
             
        $mailBody += "<TR><TD>Status</TD>"
        $mailBody += "<TD>" + $ReceiveLocationStatus + "</TD></TR>"
             
        $mailBody += "<TR><TD>URI</TD>"
        $mailBody += "<TD>" + $ReceiveLocation.InboundTransportURL + "</TD></TR>"
             
        $mailBody += "<TR><TD>Transport type</TD>"
        $mailBody += "<TD>" + $ReceiveLocation.AdapterName + "</TD></TR>"
 
        $mailBody += "</table>"
        $mailBody += "<BR><BR>"
    }
}
     
if ($StoppedReceiveLocation -eq $False)
{
    $mailBody += "<P>There are no stopped receive locations</P><BR><BR>"
}

You can obtain the full script and read more about this atMonitor your BizTalk environment using PowerShell – Port monitoring

Monitoring Windows Updates and Pending Restarts

It is important that administrators deploy the latest Microsoft product updates to servers that are running the Windows operating system. By doing this they will address and solved known issues or vulnerabilities in Microsoft products and they will keep the environment constantly updated. However when we are working with several teams (system administrators, network administrator, BizTalk administrators and so on) or sometimes without system administrators teams this task normally are forgotten or postponed several times.

With this script you can be able to monitoring Windows Updates and Pending Restarts on the servers running on your BizTalk environment using PowerShell and receive a notification by email. Servers that do not fall under these conditions will not be listed.

#########################################################
# List of computers to be monitored
#########################################################
$Servers = Get-Content .\Machines.txt
 
$results = foreach ($Computer in $Servers)
{
    try
    {
        $service = Get-WmiObject Win32_Service -Filter 'Name="wuauserv"' -ComputerName $Computer -Ea 0
        $WUStartMode = $service.StartMode
        $WUState = $service.State
        $WUStatus = $service.Status
  
        try{
            if (Test-Connection -ComputerName $Computer -Count 1 -Quiet)
            {
                #check if the server is the same where this script is running
                if($Computer -eq "$env:computername.$env:userdnsdomain")
                {
                    $UpdateSession = New-Object -ComObject Microsoft.Update.Session
                }
                else { $UpdateSession = [activator]::CreateInstance([type]::GetTypeFromProgID("Microsoft.Update.Session",$Computer)) }
                $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
                $SearchResult = $UpdateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0")
                $Critical = $SearchResult.updates | where { $_.MsrcSeverity -eq "Critical" }
                $important = $SearchResult.updates | where { $_.MsrcSeverity -eq "Important" }
                $other = $SearchResult.updates | where { $_.MsrcSeverity -eq $null }
                # Get windows updates counters
                $totalUpdates = $($SearchResult.updates.count)
                $totalCriticalUp = $($Critical.count)
                $totalImportantUp = $($Important.count)
  
                if($totalUpdates -gt 0)
                {
                    $updatesToInstall = $true
                }
                else { $updatesToInstall = $false }
            }
            else
            {
                # if cannot connected to the server the updates are listed as not defined
                $totalUpdates = "nd"
                $totalCriticalUp = "nd"
                $totalImportantUp = "nd"
            }
        }
        catch
        {
            # if an error occurs the updates are listed as not defined
            Write-Warning "$Computer`: $_"
            $totalUpdates = "nd"
            $totalCriticalUp = "nd"
            $totalImportantUp = "nd"
            $updatesToInstall = $false
        }
  
        # Querying WMI for build version
        $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -Property BuildNumber, CSName -ComputerName $Computer -Authentication PacketPrivacy -Impersonation Impersonate
  
        # Making registry connection to the local/remote computer
        $RegCon = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"LocalMachine",$Computer)
  
        # If Vista/2008 & Above query the CBS Reg Key
        if ($WMI_OS.BuildNumber -ge 6001)
        {
            $RegSubKeysCBS = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\").GetSubKeyNames()
            $CBSRebootPend = $RegSubKeysCBS -contains "RebootPending"
        }
        else{
            $CBSRebootPend = $false
        }
  
        # Query WUAU from the registry
        $RegWUAU = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")
        $RegSubKeysWUAU = $RegWUAU.GetSubKeyNames()
        $WUAURebootReq = $RegSubKeysWUAU -contains "RebootRequired"
  
        if($CBSRebootPend –OR $WUAURebootReq)
        {
            $machineNeedsRestart = $true
        }
        else
        {
            $machineNeedsRestart = $false
        }
  
        # Closing registry connection
        $RegCon.Close()
  
        if($machineNeedsRestart -or $updatesToInstall -or ($WUStartMode -eq "Manual") -or ($totalUpdates -eq "nd"))
        {
            New-Object PSObject -Property @{
                Computer = $WMI_OS.CSName
                WindowsUpdateStatus = $WUStartMode + "/" + $WUState + "/" + $WUStatus
                UpdatesToInstall = $updatesToInstall
                TotalOfUpdates = $totalUpdates
                TotalOfCriticalUpdates = $totalCriticalUp
                TotalOfImportantUpdates = $totalImportantUp
                RebootPending = $machineNeedsRestart
            }
        }
    }
    catch
    {
        Write-Warning "$Computer`: $_"
    }
}

You can obtain the full script and read more about this atMonitor your BizTalk environment using PowerShell – Monitoring Windows Updates and Pending Restarts

Event Viewer BizTalk related Errors

BizTalk Server writes all errors that occur in the environment in the Event Viewer Application Log.

Note: So is important that you maintain this log clean of noise (custom application errors, warnings of information that you can use inside your code)

With this script you can be able to monitoring the Event Viewer for BizTalk Server related errors. If the script finds any error a mail will be sent.

$getEventLog = Get-Eventlog -log application -after ((get-date).AddHours(-4)) -EntryType Error | Where-Object {($_.Source -eq 'BizTalk Server')}

You can obtain the full script and read more about this atBizTalk DevOps: Monitor your BizTalk environment using PowerShell –Event Viewer BizTalk related Errors

Monitor and Manage Messages Being Archived Locally Into the Hard Drive

Is very common in integration scenarios to see messages being archived locally into the hard drive – either by using a pipeline component like BizTalk Archiving – SQL and File or by simple using the default functionalities in BizTalk like filters:

  • Create a Send Port with a filter expression equal to the name of Receive Port or type of the message you want to archive. (How to Configure Filters for a Send Port)
This can happen for several reasons, for example:
  • The messages needs to be archived for legal reasons (normally (recommended) we use an “external” repository – not a local hard drive in the server)
  • or because it is practical and useful to have the file so it can easily be reprocessed in case of failure
The common problem with some of these approach is that normally we tend to implement the archive mechanism and we forget to implement a cleaning mechanism and we end up with several problems after a while:
  • The most critical –> disk full, causing processes to fail or other problems even more critical
  • Many files in a folder, causing performance problems when we are trying to perform operations on it à According to some articles, the lookup time of a directory increases proportional to the square of the number of entries and performance seems to drop between 1000 and 3000 files (the important is not the exact number itself but knowing that a high number may cause problems).

And if you have an integration process that processes hundreds of messages, you can quickly get this kind of problems. With this script you can be able to automatically monitoring these folders on the servers using PowerShell.

$Hours = "12"
$LastWrite = $Now.AddHours(-$Days)
 
$Directories = Get-ChildItem "D:\BizTalkApplications\Archive" -Recurse | ?{ $_.PSIsContainer } | Select-Object FullName
 
foreach ($directory in $Directories)
{
    $zipFile = "E:\BackupFileWarehouse\" + $directory.FullName.Substring($directory.FullName.LastIndexOf(":")+2).Replace("\","_") + "_" +  (get-date -f yyyyMMdd_hhss).ToString() + ".zip"
  
    $filelist = get-childitem $directory.FullName |
                                where-object {$_.LastWriteTime -le (get-date).AddHours(-$Hours)} |
                                where-object {-not $_.PSIsContainer}
  
    if($filelist.Count -gt 0)
    {
        $filelist | format-table -hideTableHeaders FullName | out-file -encoding utf8 -filepath lastmonthsfiles.txt
                    & 'C:\Program Files (x86)\7-Zip\7z.exe' a $zipFile `@lastmonthsfiles.txt
  
        $filelist | %{Remove-Item $_.FullName }
        rm lastmonthsfiles.txt
    }
}

You can obtain the full script and read more about this atBizTalk DevOps: Monitor your BizTalk environment using PowerShell – Manage messages being archived locally into the hard drive

See also

Suggested reading following resources:

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.