Saving suspended messages in BizTalk (filtering on orchestration or port name)

Last week, I needed to save 700+ suspended messages to file. I didn’t want to go in to each instance and click ‘save to file’ 700 times. A quick search in the web did not find what I want, however there were a number of articles about extracting messages from the BizTalk tracking database. One of which is this excellent article by Thiago Almeida.

My scenario was for an existing BizTalk 2004 implementation in the company and is only a once-off thing I need to do. For the newer BizTalk 2006 applications, there is the ‘Failed Message Routing’ feature that can be enabled on send ports and receive ports. The failed messages could then be easily subscribed to a send port to output to file.

Then it occured to me that the WMI script Terminate.vbs has the option to save the messages before terminating the instances (http://go.microsoft.com/fwlink/?LinkID=107591 and slightly updated for 2009 ). Thus changing this script to do what I want required the least effort. I could just use the script as it is to save all the messages and terminate the instances. However it didn’t take much to modify it to take a parameter for filtering on an instance name and to only save messages (and not terminate them). Below is the usage description of the save_messages.vbs script and the actual script. It works for BizTalk 2004, 2006 and 2009.

There is also a replacement of the Terminate.vbs script: Biztalk Terminator.

Usage:
cscript save_messages.vbs < -Z | -A | -DIS | -SR | -SNR > [Port/Orchestration name]

-Z saves all “Zombie” instances (e.g. completed with discarded messages)
-A saves all suspended and zombie instances as well as all routing failure reports
-SR saves suspended resumable instances only
-SNR saves suspended non-resumable instances only
-DIS saves all dehydrated ‘isolated adapter’ instances
optionally supply the name of the orchestration or port name to filter on specific instances

Ensure that the C:\Temp folder exists before running as that is where it saves the instances

Example: cscript save_messages.vbs -z “E-Reporting Data Transform Port”

Visual Basic Script:

‘ save_messages.vbs
‘ Enter save_messages.vbs with no arguments from a command prompt for usage
‘ This script needs to be run under a user account that is a member of the BizTalk Administrators
‘ group. This script needs to be run on a machine that is configured with BizTalk administration
‘ tools.

dim objBtsWmiNS, objMsg, svcinsts, inst, msg, ndx, size

Dim aryHostNames()
Dim aryObjQueues()
Dim aryHostBatchSize()

Dim strKey2Instance
Dim strQuery2Msg
Dim strServiceName

On Error Resume Next
Dim objArgs: Set objArgs = WScript.Arguments
If ( objArgs.Count = 0 OR objArgs.Count > 2) Then
PrintUsage()
wscript.quit 0
End If

wmiQuery = “”

‘ServiceStatus = 16 – ‘Completed With Discarded Messages’ in BizTalk Server 2004
‘ServiceStatus = 32 – ‘Suspended (not resumable)’
‘ServiceStatus = 4 – ‘Suspended (resumable)’
‘ServiceClass = 64 – ‘Routing Failure Report’
‘ErrorId = “0xC0C01B4C” – is how ‘Completed With Discarded Messages’ are exposed in BizTalk Server 2006

If (objArgs(0) = “-Z” OR objArgs(0) = “-z”) Then
wmiQuery = “select * from MSBTS_serviceinstance where ServiceStatus=16 OR ErrorId=’0xC0C01B4C'”
End If

If (objArgs(0) = “-A” or objArgs(0) = “-a”) Then
wmiQuery = “select * from MSBTS_serviceinstance where ServiceStatus=4 OR ServiceStatus=32 OR ServiceStatus=16 OR ErrorId=’0xC0C01B4C’ OR ServiceClass=64”
End If

If (objArgs(0) = “-SR” or objArgs(0) = “-sr”) Then
wmiQuery = “select * from MSBTS_serviceinstance where ServiceStatus=4”
End If

If (objArgs(0) = “-SNR” or objArgs(0) = “-snr”) Then
wmiQuery = “select * from MSBTS_serviceinstance where ServiceStatus=32”
End If

If (objArgs(0) = “-DIS” or objArgs(0) = “-dis”) Then
wmiQuery = “select * from MSBTS_serviceinstance where ServiceClass=32 AND ServiceStatus=8”
‘ServiceClass = 32 ‘Isolated Adapter
‘ServiceStatus = 8 ‘Dehydrated
End If

saveMessagesBeforeTermination = True

If ( objArgs.Count > 1) Then
strServiceName = objArgs(1)
End If

If(wmiQuery = “”) Then
PrintUsage()
wscript.quit 0
End If

wscript.echo “–>Connecting to BizTalk WMI namespace”
Set objBtsWmiNS = GetObject(“WinMgmts:{impersonationLevel=impersonate, (security)}\\.\root\MicrosoftBizTalkServer”)
If Err <> 0 Then
CheckWMIError
wscript.quit 0
End If

wscript.echo “–>Getting BizTalk host collection”
Set hosts = objBtsWmiNS.ExecQuery(“select * from MSBTS_HostSetting”)
If Err <> 0 Then
CheckWMIError
wscript.quit 0
End If

hostCount = hosts.count

ReDim aryHostNames(hostCount – 1)
ReDim aryObjQueues(hostCount – 1)
ReDim aryHostBatchSize(hostCount – 1)

wscript.echo “–>Retrieve BizTalk host names and loading host queues”
ndx = 0
For Each host in hosts
wscript.echo “Found host ” & host.Properties_(“Name”)
aryHostNames(ndx) = host.Properties_(“Name”)
Set aryObjQueues(ndx) = objBtsWmiNS.Get(“MSBTS_HostQueue.HostName=””” & aryHostNames(ndx) & “”””)
If Err <> 0 Then
CheckWMIError
wscript.quit 0
End If
ndx = ndx + 1
Next

wscript.echo “–>Getting collection of service instances”
Set svcinsts = objBtsWmiNS.ExecQuery(wmiQuery)

‘Iterate through instances and save them in host-specific arrays.

wscript.echo “–>Start iterating service instances”
totalCount = 0
For Each inst in svcinsts
If (objArgs.Count = 1 Or (objArgs.Count > 1 And strServiceName = inst.Properties_(“ServiceName”) ) ) Then

wscript.echo “Found suspended instance “”” & inst.Properties_(“ServiceName”) & “”” on host ” & inst.Properties_(“HostName”)
‘Resolve host index
For hostIdx = 0 To hostCount-1
If aryHostNames(hostIdx) = inst.Properties_(“HostName”) Then
Exit For
End If
Next

’16 is an internal service class that cannot be terminated
If 16 = inst.Properties_(“ServiceClass”) Then
wscript.echo “Skipping BizTalk internal service instances (they cannot be terminated anyway)”
Else
’64 is a routing failure report and doesn’t have messages that can be saved
If 64 = inst.Properties_(“ServiceClass”) Or 16 = inst.Properties_(“ServiceClass”) Then
saveMessagesBeforeTermination = False
End If

errorCountSavingMessages = 0
If saveMessagesBeforeTermination Then
strQuery2Msg = “select * from MSBTS_MessageInstance where ServiceInstanceID=””” & inst.Properties_(“InstanceId”) & “”””
Set msgInsts = objBtsWmiNS.ExecQuery(strQuery2Msg)
For Each msg in msgInsts
msg.SaveToFile “C:\Temp”
If Err <> 0 Then
CheckWMIError
wscript.echo “Failed to save MSBTS_MessageInstance”
wscript.echo Err.Description & Err.Number
errorCountSavingMessages = errorCountSavingMessages + 1
Else
wscript.echo “Saved message ” & msg.Properties_(“MessageInstanceID”)
End If
Next
End If

totalCount = totalCount + 1
End If

End If
Next

‘ Delete whatever is left
For hostIdx = 0 To hostCount-1
If aryHostBatchSize(hostIdx) > 0 Then
TerminateAccumulatedInstacesForHost hostIdx
End If
Next

wscript.echo “SUCCESS> ” & totalCount & ” instances were found and attempted to be saved”

‘This subroutine deals with all errors using the WbemScripting object.
‘Error descriptions are returned to the user by printing to the console.
Sub CheckWMIError()

If Err <> 0 Then
On Error Resume Next
Dim strErrDesc: strErrDesc = Err.Description
Dim ErrNum: ErrNum = Err.Number
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

‘wscript.quit 0
End If

End Sub

Sub PrintUsage()
wscript.echo “Usage:”
wscript.echo “cscript save_messages.vbs < -Z | -A | -DIS | -SR | -SNR > [Port/Orchestration name]”
wscript.echo
wscript.echo ”  -Z saves all “”Zombie”” instances (e.g. completed with discarded messages)”
wscript.echo ”  -A saves all suspended and zombie instances as well as all routing failure reports”
wscript.echo ”  -SR saves suspended resumable instances only”
wscript.echo ”  -SNR saves suspended non-resumable instances only”
wscript.echo ”  -DIS saves all dehydrated ‘isolated adapter’ instances”
wscript.echo ”  optionally supply the name of the orchestration or port name to filter on specific instances”
wscript.echo
wscript.echo ”  Ensure that the C:\Temp folder exists before running as that is where it saves the instances”
wscript.echo
wscript.echo ”  Example: cscript save_messages.vbs -z “”E-Reporting Data Transform Port”””
wscript.echo
End Sub

Advertisements

7 comments so far

  1. hanu on

    Thank you very much, i have close to 3000 messages suspended, your script made my life easy. I can extract them and then read the keys , terminate the messages and can resubmit them useing the keys.

  2. unpop on

    I still get invalid character line 1, char 1

    • vincent on

      You might have copied some extra characters from the page? Not seen an error like this before. The script is pretty much the same as on Microsoft’s site but with some small changes only.

  3. Sean on

    It is definitely because the characters are different when you copy and paste into notepad. The apostrophes have to be changed, and a few other characters. I ran into the exact same problem and I changed everything and it worked fine.

  4. Sean on

    Hey Vincent, First off I would like to thank you for this script, it works really great. One question I had though was can this be altered so that rather than searching for suspended messages by Orchestration name, you could use the Application name instead?

  5. WiredEarp on

    Agreed – the problem is usually due to the apostrophies changing to ‘smart quotes’ instead of the generic vertical quote. Seen this a few times with cut & paste code.

  6. JeffW on

    This is a very useful script! Only problem I have is I need to save all the messages for an instance of a send port that uses ‘Ordered Delivery’. That causes more than one message to be associated with the same send port instance (like in a queue). Any way to adapt this script to handle that?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: