Saving Suspended Messages using WMI, PowerShell and the Microsoft.BizTalk.Operations Assembly (Part I)

Often, there’s a need to save out suspended messages out to a file, so that we can resubmit/inspect them later. From the BizTalk Admin Console, we can right-click the suspended service instance -> Show Messages. When the messages associated with that service instance opens up, we can right-click -> Save to File. However, for hundreds (possibly thousands) of suspended instances, this is not possible.

One of the options of doing this is using the wonderful BizTalk Terminator Tool (https://www.microsoft.com/en-us/download/details.aspx?id=2846). If you’re okay terminating these instances, you can use this to save out the suspended messages, before terminating the suspended service instances. The only drawback to this approach is that you have no option but to terminate the instances. [After you click Connect on the first Terminator window, you need to click the Delete button at the bottom, and then select the ‘Terminate Instances’ option to get to this screen]. 

 

What if you wanted to retain the suspended instances, and yet save the messages out to disk?
Well, time to write some WMI code. We chose to use a PowerShell script in this case. We could easily have called the same WMI queries using VBScript or, C#. So, here is the code -
[Original code courtesy - Tomas Restrepo's blog : https://winterdom.com/2006/09/btssuspendedmessaginginstanceswithpowershell]

#
# Use:
# C:\.\Save_Suspended_msgs.ps1 -action list
# C:\.\Save_Suspended_msgs.ps1 -action save
"c:\temp\Suspended_msgs" ([optional]> log.file) 

#
# declare our parameters: the action to take, and an optional
# path to save messages to
#
param(
   [string] $action=$(throw 'need action'),
   [string] $path=$(if ($action -eq 'save') { throw 'need path' })
)
$counter = 0 

function bts-get-messaging-svc-instances()
{
   get-wmiobject MSBTS_ServiceInstance `
      -namespace 'root\MicrosoftBizTalkServer'
      -filter '(ServiceClass=1 or ServiceClass=4) and ServiceStatus = 4 '

#

# save the message associated to the
# specified messaging Service Instance
#
function
bts-save-message([string]$msgid, [string]$sname)
{
   "msgid is $msgid"
   "ServiceName is $sname"
   "msg_counter is $counter"
   $msg = get-wmiobject MSBTS_MessageInstance `
      -namespace 'root\MicrosoftBizTalkServer'
      -filter "ServiceInstanceID = '$msgid'"
      $newpath = (Join-Path $path $sname)
     "new path is $newpath"
     $r_code= (test-path $newpath)
     "return code is $r_code"
     if ($r_code -eq $False)
     {
         md $newpath
        "new directory created"
     }
       if ($msg.psbase.length -gt 0)     
       {
        foreach($m in $msg)
                     {           
$m.psbase.invokemethod('SaveToFile', ($newpath))
             "Message from ServiceInstanceID=$msgid saved to $newpath."
                     }
       }

#
# main script
#
switch ( $action )
{
   'list' {
# bts-get-messaging-svc-instances   
      bts-get-messaging-svc-instances |
      bts-get-messaging-svc-instances |
         fl * 

# fl InstanceId, ServiceName, SuspendTime,HostName,
# ServiceStatus, ServiceClass, ErrorId, ErrorDescription
   }
   'save' {
      bts-get-messaging-svc-instances |
          %{ $counter++; bts-save-message $_.InstanceID $_.ServiceName }     

   }
}

In the bts-get-messaging-svc-instances() function, we have –
get-wmiobject MSBTS_ServiceInstance `  

-namespace 'root\MicrosoftBizTalkServer' `
-filter '(ServiceClass=1 or ServiceClass=4) and ServiceStatus = 4 '

 

We are filtering on Service instances with ‘ServiceClass = 1’ (this gets Orchestration suspended instances) or, ‘ServiceClass = 4’ (messaging service instances). ‘ServiceStatus = 4’ means Suspended (Resumable). These are the other Service Status codes, in case you need it:

//******** List of WMI Service Statuses ********

//ServiceStatus = 1 - Ready To Run
//ServiceStatus = 2 - Active
//ServiceStatus = 4 - Suspended (Resumable)
//ServiceStatus = 8 - Dehydrated
//ServiceStatus = 16 - Completed With Discarded Messages' in BizTalk Server 2004
//ServiceStatus = 32 - Suspended (Not Resumable)
//ServiceStatus = 64 - In Breakpoint 

Usage : To use this script, save this to a file (say at the path - C:\script\Save_Suspended_msgs.ps1 ), and run this from the PowerShell command prompt:
PS C:\Users\Administrator> C:\script\Save_Suspended_msgs.ps1 -action save "c:\temp\Suspended_msgs"

 

This would create separate folders for each suspended instance type under the ‘Suspended_msgs’folder specified above. So, if you have suspended instances for two different Orchestration types, it would create folders named after those Orchestrations and save out the messages in their respective folders.
All good, right? Well, this solution works great as long as your suspended orchestration instances don’t contain multiple suspended messages. We cover in Part II of this article how to handle this specific case.

Written by
Arindam Paul Roy

Reviewed by
Jainath V R

Microsoft India GTSC