I have uploaded an improved versión of this script in the TechNet Wiki Site
You can now filter by a suspension time range also! 🙂
Background of suspended messages.
BizTalk Server stores messages associated with suspended pipelines in the MessageBox database. If a failure occurs in the pipeline, BizTalk Server suspends the instance of a message. There are two types of suspended service instances:
- Suspended instances that you can resume.
- Suspended instances that you cannot resume. For example, if an instance is corrupt.
Depending on the cause of the suspension, you may be able to resume services that BizTalk Server suspends — for example, if an orchestration hits a Suspend shape, or if a transport was unable to deliver a message, BizTalk Server does not automatically remove suspended instances that you cannot resume from the MessageBox database. You can choose to save a service instance to disk before removing it from the suspended queue.
Impact of Suspended Messages
Each suspended message is going to be stored into the suspended queue for that host (See Host queue tables post in this blog) This implies:
- Spool table will have references for that messages
- Each internal stored procedure that the BizTalk engine runs have to “filter” and execute even more records than usual which in a 100.000 execution will have a negative impact (even more in a low latency scenario in which the MaxReceiveInterval (BizTalk 2006) or Pooling Intervals (BizTalk 2010) settings are aggressively reduced)
- Throttling due to message count in database threshold will be affected since suspended messages are included in the Message count in database calculation (because of the Spool size), throttling of message publishing can occur even if the BizTalk server is experiencing low or no load.
Why this script?
This script is intended to be as a tool to deal with BizTalk suspended messages, specially if the environment is suffering with massive suspended messages.
Important supportability information
This script may not be supported by Microsoft as is going to be coded by you, Microsoft has not tested it.
With this script you will be able to:
Terminate or resume a set of suspended messages that match:
A suspended error code (mandatory)
BizTalk host name (optional, if missing will terminate or resume all messages with that error code across the whole BizTalk group)
if resume or terminate actions are selected, the script will save those messages before performing any actions (if required)
Save suspended messages to a folder location
In the code you can have a look at the usage section to learn how to use it.
The account running the script must:
Have vbs scripting execution rights
Membership to BizTalk Administrator group
How to execute it
Variables must be set within the code. No parameters
needed. The script must be executed in a cscript context:
In this example the tools is saving all suspended messages with error code 0xc0c01680. Since HostNameToCompare is empty, messages
across the whole group (all hosts) will be saved.
After the execution, the folder c:\SavedBizTalkMessages\new will look like:
the existence of two kinds of messages:
- *.out contains the content of the message.
- *.xml contains de context of the message.
Here is the code:
‘ THIS CODE AND INFORMATION ARE PROVIDED “AS IS” WITHOUT WARRANTY OF ANY
‘ KIND, WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
‘ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
‘ Variable Assignements:
‘ HostNameToCompare = “HostName” ‘if empty, will delete all suspended messages with error code sErrorCode across the whole BizTalk Group.
‘ sErrorCode = “0xC0C01B4e” ‘this is the error code to use as filtering when terminating/resuming suspended message instances
‘ intAction = 1 ‘Will Terminate the message
‘ intAction = 2 ‘will Resume the message
‘ intAction = 3 ‘will JUST save the message WITHOUT terminate or resume it
‘ SaveToFileFolder = ‘if a folder is set, the process will try to save every message before performing an action. IF THERE IS AN ERROR WHILE SAVING THE MESSAGE IT WILL NOT BE RESUMED/TERMINATED
‘ the Script will act as intAction with every message that matches HostNameToCompare and sErrorCode.
‘ intDeleteAllExistingFiles ‘IF 1, will delete all the files on SaveToFileFolder path before saving the messages.
Dim sQuery, intSet, Inst, HostName, intCounter, SaveToFileFolder , MessageSet, InstMessageSet, fso
Dim intAction, sErrorCode, strInstanceFullPath, sCustomText, intProcessedMessageCount, intTotalMessageCount
intDeleteAllExistingFiles = 0
HostNameToCompare = “BizTalkServerApplication”
sErrorCode = “0xc0c01680”
intAction = 3
SaveToFileFolder = “C:\SavedBizTalkMessages\new” ‘*** Never add the last “\” to the folder path, will fail
ThereIsAnError = 0
intTotalMessageCount = 0
intDeleteAllExistingFiles = 1
On Error Resume Next
wscript.echo “************ CURRENT SCRIPT PARAMETERS ************* ”
wscript.echo ” HostNameToCompare: ” & HostNameToCompare
wscript.echo ” sErrorCode: ” & sErrorCode
wscript.echo ” intAction: ” & intAction
wscript.echo ” SaveToFileFolder: ” & SaveToFileFolder
wscript.echo “**************************************************** ”
if sErrorCode =”” Then
wscript.echo “The Variable sErrorCode must be set… exiting.”
quit ‘this will raise an exception and will exit the script 🙂
if intAction = 1 Then
sCustomText = “Terminated”
if intAction = 2 Then
sCustomText = “Resumed”
sCustomText = “Saved To Disk”
intProcessedMessageCount = 0
sQuery = “select * from MSBTS_serviceinstance where ServiceStatus=4 and ErrorId =’“ & sErrorCode & “‘”
Set intSet = GetObject(“Winmgmts:!root\MicrosoftBizTalkServer”).ExecQuery(sQuery)
If Err <> 0 Then
PrintWMIErrorthenExit Err.Description, Err.Number
intTotalMessageCount = intSet.Count
wscript.echo “Query succsesfully executed, “ & intTotalMessageCount & ” Suspended instances found with the current parameters.”
If intTotalMessageCount > 0 Then
intCounter = 1
if intDeleteAllExistingFiles = 1 then ‘if existing previous files must be deleted…
Set fso = CreateObject(“Scripting.FileSystemObject”)
fso.DeleteFile(SaveToFileFolder & “\*.*”)
set fso = nothing
For Each Inst In intSet
HostName = Inst.HostName
if HostNameToCompare =“” Then
‘if HostNameToCompare is empty assuming all instances must be suspended/terminated, So we assing the var HostNameToCompare with Inst.HostName value. The next if will be processed all the times.
HostNameToCompare = Inst.HostName
wscript.echo “Attempting to operate with instance “ & intCounter & “/” & intSet.Count & ” on host “ & HostName
if HostToCompare = HostName Then
if SaveToFile <> “” Then
strInstanceFullPath = “select * from MSBTS_MessageInstance where ServiceInstanceID ='” & Inst.InstanceId & “‘”
‘wscript.echo “full path ” & strInstanceFullPath
Set MessageSet = GetObject(“Winmgmts:!root\MicrosoftBizTalkServer”).ExecQuery(strInstanceFullPath)
for each InstMessageSet in MessageSet
‘Should have just 1 message plus the context, which means two physical files per message.
On Error Resume Next
ThereIsAnError = Err
if ThereIsAnError = 0 then
On error resume next
‘if intAction = 3, just saving action will done
if intAction = 1 Then
if intAction = 2 then
If Err <> 0 Then
PrintWMIErrorThenExit Err.Description , Err.Number
wscript.echo “Message instance succsesfully “ & sCustomText
intProcessedMessageCount = intProcessedMessageCount + 1
wscript.echo “The Message has not been “ & sCustomText & ” due to an error saving the message.”
intCounter = intCounter + 1
wscript.echo “No Suspended instances found with error code: “ & sErrorCode & “… Exiting”
wscript.echo “The Script has ” & sCustomText & ” ” & intProcessedMessageCount & ” instance(s) of “ & intTotalMessageCount
Sub PrintWMIErrorThenExit(strErrDesc, ErrNum)
On Error Resume Next
Dim WMIError : Set WMIError = CreateObject(“WbemScripting.SwbemLastError”)
If ( TypeName(WMIError) = “Empty” ) Then
wscript.echo strErrDesc & ” (HRESULT: “ & Hex(ErrNum) & “).”
wscript.echo WMIError.Description & “(HRESULT: “ & Hex(ErrNum) & “).”
Set WMIError = nothing