Extended Visual Basic Script to deal with BizTalk Suspended Messages
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.
Requirements:
The account running the script must:
- Have vbs scripting execution rights
- WMI 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:
Cscript NameOfTheScript.vbs
Demonstration:
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:
*Note
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
' PURPOSE.
'--------------------------------------------------------------------------
'USAGE
' 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.
'--------------------------------------------------------------------------
Option Explicit
TerminateSuspendedMessages
Sub TerminateSuspendedMessages()
Dim HostNameToCompare
Dim sQuery, intSet, Inst, HostName, intCounter, SaveToFileFolder , MessageSet, InstMessageSet, fso
Dim intAction, sErrorCode, strInstanceFullPath, sCustomText, intProcessedMessageCount, intTotalMessageCount
Dim ThereIsAnError
Dim intDeleteAllExistingFiles
intDeleteAllExistingFiles = 0
'PROPERTIES------------------------------------------------------------
HostNameToCompare = "BizTalkServerApplication"
HostNameToCompare =""
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 "**************************************************** "
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 :-)
end if
if intAction = 1 Then
sCustomText = "Terminated"
Else
if intAction = 2 Then
sCustomText = "Resumed"
Else
sCustomText = "Saved To Disk"
end if
End if
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
Else
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
end if
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
end if
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
InstMessageSet.SaveToFile SaveToFileFolder
ThereIsAnError = Err
next
End if
if ThereIsAnError = 0 then
On error resume next
'if intAction = 3, just saving action will done
if intAction = 1 Then
Inst.Terminate
Else
if intAction = 2 then
Inst.Resume
end if
End if
If Err <> 0 Then
PrintWMIErrorThenExit Err.Description , Err.Number
Else
wscript.echo "Message instance succsesfully " & sCustomText
intProcessedMessageCount = intProcessedMessageCount + 1
end if
else
wscript.echo "The Message has not been " & sCustomText & " due to an error saving the message."
end if
End If
intCounter = intCounter + 1
Next
Else
wscript.echo "No Suspended instances found with error code: " & sErrorCode & "... Exiting"
End If
wscript.echo "The Script has " & sCustomText & " " & intProcessedMessageCount & " instance(s) of " & intTotalMessageCount
end if
End Sub
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) & ")."
Else
wscript.echo WMIError.Description & "(HRESULT: " & Hex(ErrNum) & ")."
Set WMIError = nothing
End If
'bail out
wscript.quit 0
End Sub
Enjoy
Comments
- Anonymous
March 21, 2014
Script is too good and adoptive to my environment, but need to delete only messages which is more than 14 days, can you let me know where shall incorporate this ??Thank you - Anonymous
October 29, 2014
Hi Hari, i am changing it to include that functionalitie. I will post it soon. Thank you! - Anonymous
November 05, 2014
Hi Again Hari, I have uploaded improved version of this script in the MSDN Code Gallerygallery.technet.microsoft.com/Visual-Basic-script-to-8542997b(You can filter now by suspensión Time frame) :-)Agustín.