BizTalk Tips & Things

Agustin Mantaras BizTalk Blog

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

http://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