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

https://social.technet.microsoft.com/wiki/contents/articles/28157.biztalk-script-to-deal-with-suspended-messages-vbs.aspx

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 Sonrisa