Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
Windows Server

BizTalk Server 2009 : Editing and Resubmitting Suspended Messages (part 2) - Pseudo-Walkthrough to Perform Edits and Resubmits

2/7/2013 5:21:14 PM

8. Pseudo-Walkthrough to Perform Edits and Resubmits

Exercise 1 describes in detail the steps to edit and resubmit a suspended message. The walkthrough in Exercise 1 follows the steps in Figure 2, shown earlier in this section.

EXERCISE 1: Creating a New Windows Service Project and Aplying Setings

Create the Suspended Message Handler Service

The following steps are used to create the Windows service that will poll for suspended messages:

  1. Start Microsoft Visual Studio 2008.

  2. On the File menu, point to New, and then click Project.

  3. Click Visual Basic Projects under Project Types, and then click Windows Service under Templates.

  4. Type BizTalkSuspendedMessageHandlerService in the Name text box. Change location if necessary. Click OK.

  5. In the Code Editor window, right-click Design View, and then click Properties.

  6. In the Properties pane, click the Add Installer link.

  7. Change the display name to BizTalk Suspended Message Handler Service.

  8. In the Properties pane for serviceInstaller1, change the ServiceName property to Service1.


    The ServiceName property needs to match the name of the service class.

  9. Change StartType to Automatic.

  10. In the Code Editor window in Design view, click serviceProcessInstaller1.

Note that the account is set to User. When the service is installed, it will need to be set to an account that has access to the BizTalk resources.

Add a Configuration File

  1. Right-click the project and choose Add New Item.

  2. Double-click Application Configuration File in the right-hand pane.

  3. Between the configuration tags paste the following XML:

           <add key="SuspendedMessagesTempFileLocation" value="MyDrive:\MyFolder" />
           <add key="SuspendedMessagesFileLocation" value="MyDrive:\MyFolder" />
           <add key="ProcessingInstruction" value="MyInfoPathProcessingInstruction"/>

  4. Replace "MyDrive:\MyFolder" with appropriate paths. SuspendedMessagesTempFileLocation is the location where the message parts and context will get saved. SuspendedMessagesFileLocation is the location for the SuspendedMessage instance.

  5. Replace processing instructions if desired within the XML file to point to the proper InfoPath form you want to open. An example of one is

solutionVersion='' productVersion='11.0.5531' PIVersion=''
SuspendedMessage.xsn' language='en-us'

Add References and Class Variables

  1. Add a reference within the project to System.Management.dll and System.Configuration.dll.

  2. In Solution Explorer, right-click Service1.vb, and then click View Code.

  3. At the top of the page add the following Imports statements:

    Imports System.Management
    Imports System.Xml
    Imports System.IOt
    Imports System.Configuration

  4. Within the class declaration, just under

private components as System.ComponentModel.Container = nothing

add the following:

private watcher as ManagementEventWatcher

Add Code to OnStart

  1. In Solution Explorer, right-click Service1.cs, and then click View Code.

  2. In the OnStart event handler, replace the comments with the following:

    'Listen for messages
    Dim scope as string = "root\\MicrosoftBizTalkServer"
    Dim wqlQuery as string = "Select * from MSBTS_ServiceInstanceSuspendedEvent"
    watcher = new ManagementEventWatcher(scope, wqlQuery)
    AddHandler watcher.EventArrived, AddressOf MyEventHandler watcher.Start

This will start listening for the ServiceInstanceSuspended event.

Add Custom Event Handler

  1. Add the following two procedures to the Service 1 class:

    Public Shared Sub MyEventHandler(sender As Object, e As EventArrivedEventArgs)
          ' Read the TempDirectoryName from config file
          Dim TempDirectoryName As String = _
          ' Read WaitingDirectoryName
          ' This folder is the location for the new XML document that this service
          ' creates based on context and message parts.
          Dim WaitingDirectoryName As String = _
          ' If you want to add processing instructions for InfoPath
          ' this will get it.
          Dim pi As String = _
          Dim waitingMessageFileName As String
          ' xwriter for suspended message
          Dim xwriter As XmlTextWriter

    'Look up MSBTS_ServiceInstanceSuspendedEvent
          'in the BTS04/06 documentation for additional properties
          Dim ErrorID As String = e.NewEvent("ErrorID").ToString()
          Dim ErrorCategory As String = e.NewEvent("ErrorCategory").ToString()
          Dim ErrorDescription As String = e.NewEvent("ErrorDescription").ToString()
          Dim ServiceStatus As String = e.NewEvent("ServiceStatus").ToString()
          Dim ServiceInstanceID As String = e.NewEvent("InstanceID").ToString()
          Dim enumOptions As New EnumerationOptions()
          enumOptions.ReturnImmediately = False
          Dim MessageInstancesInServiceInstance As New _
    ManagementObjectSearcher("root\MicrosoftBizTalkServer", _
    "Select * from MSBTS_MessageInstance where ServiceInstanceID='" + _
    ServiceInstanceID + "'", enumOptions)
          'Enumerate through the result set
          Dim MessageInstance As ManagementObject
          For Each MessageInstance In MessageInstancesInServiceInstance.Get()
             ' The only way to get at the message body is to utilize the 
    SaveToFile ' method on the BTS_MessageInstance WMI Class. ' This saves all of the message information to files. ' Each MessagePart making up a message is saved in separate files, ' typically you only get a Body, but you must cater to multipart ' messages to cover all scenarios. ' As well as the MessageParts, a context file is created; you need to ' use this to extract the MessagePartIDs and MessagePartNames so you ' can then work out the file names to open! ' The context file name format is ' <MessageInstanceID>_context.xml. ' And then the actual message information file name format is ' <MessageInstanceID>_<MessagePartID>[_<MessagePartName>].out ' MessagePartName is only required if the MessagePart has a name! ' You need to build this file name up so you can load it up - ' no hacking here! ' Save the files MessageInstance.InvokeMethod("SaveToFile", New Object() _ {TempDirectoryName}) ' Get the MessageInstanceID Dim MessageInstanceID As String = _ MessageInstance("MessageInstanceID").ToString() ' You now need to load the context file up to get the MessagePart ' information Dim ContextFileName As String

    ' Load the context file up
            Dim doc As New XmlDocument()
            ' Pull out context properties that you are interested in
            Dim ReceivedFileName As String = GetContextProperty(doc, _
            Dim InboundTransportLocation As String = GetContextProperty(doc, _
            Dim InterchangeID As String = GetContextProperty(doc, _
            Dim ReceivePortID As String = GetContextProperty(doc, _
            Dim ReceivePortName As String = GetContextProperty(doc, _
            ' Create an XmlWriter to store the data.
            ' This will get written to a file when complete.
            waitingMessageFileName = [String].Format("")
            xwriter = New XmlTextWriter(waitingMessageFileName, _
                    xwriter.Formatting = Formatting.Indented
            'Write the ProcessingInstruction node.
            xwriter.WriteProcessingInstruction("mso-infoPathSolution", pi)
            xwriter.WriteProcessingInstruction("mso-application", _
            xwriter.WriteComment(String.Format("Created on {0}", _
             ' Write the context information
             xwriter.WriteStartElement("ns0", "SuspendedMessage", _
            xwriter.WriteElementString("ReceivedFileName", ReceivedFileName)
            xwriter.WriteElementString("InboundTransportLocation", _
            xwriter.WriteElementString("InterchangeID", InterchangeID)
            xwriter.WriteElementString("ReceivePortID", ReceivePortID)
            xwriter.WriteElementString("ReceivePortName", ReceivePortName)
            xwriter.WriteEndElement() ' Context
            ' Start the Message Element

    ' Use XPath to return all of the MessagePart(s) referenced in the
            ' context
            ' You can then load the file up to get the message information
            Dim MessageParts As XmlNodeList = _
            Dim MessagePart As XmlNode
            For Each MessagePart In MessageParts
                ' Pull the MessagePart info out that you need
                Dim MessagePartID As String = MessagePart.Attributes("ID").Value
                Dim MessagePartName As String = 
    MessagePart.Attributes("Name").Value Dim Contents As String Dim FileName As String ' If you have a MessagePartName, append this to the end of ' the file name. It's optional so if you don't have it, don't ' worry about it. If MessagePartName.Length > 0 Then FileName = [String].Format("") End If ' Load the message, place it in canonical schema, and submit it. ' Create an instance of StreamReader to read from a file. ' The using statement also closes the StreamReader. Dim sr As New StreamReader(FileName) Try ' Read to end of file Contents = sr.ReadToEnd() Finally sr.Dispose() End Try ' Write out MessagePart data xwriter.WriteStartElement("MessagePart") xwriter.WriteElementString("MessagePartId", MessagePartID) xwriter.WriteElementString("Name", MessagePartName) xwriter.WriteStartElement("Contents") ' Write out contents as CDATA. xwriter.WriteCData(Contents) xwriter.WriteEndElement() ' Contents xwriter.WriteEndElement() ' MessagePart Next MessagePart xwriter.WriteEndElement() ' Message xwriter.WriteEndElement() ' SuspendedMessage xwriter.Close() Next MessageInstance End Try End Sub 'MyEventHandler

    ' Helper function to pull out context properties given a property name
    Private Shared Function GetContextProperty(doc As XmlDocument, propertyName 
    As _ String) As String Dim MessageContext As XmlNode = _ doc.SelectSingleNode(("/MessageInfo/ContextInfo/Property[@Name='" + _ propertyName"']")) If Not (MessageContext Is Nothing) Then If Not (MessageContext.Attributes("Value") Is Nothing) Then Return MessageContext.Attributes("Value").Value Else Return "Value no found" End If Else Return "Property not found" End If End Function 'GetContextProperty

Compile Project and Install Windows Service

  1. Under the Build menu, select Build Solution.

  2. Open a command prompt and change to the project root directory of this project.

  3. From the command line type the following:

    "<Drive>:\WINDOWS\Microsoft.NET\Framework\ v2.0.50727\installutil.exe" "bin\Debug\BizTalkSuspendedMessageHandlerService.exe"

    "<Drive>" is the drive letter where Windows is installed. This will install the EXE as a Windows service.

  4. A prompt will come up asking you for credentials. Enter credentials that have access to the BizTalk resources. After entering credentials, a message should be returned indicating success and that the install was completed.

  5. From Administrative Tools, open Services.

  6. Find the new service, Service1. Right-click and select Start. The service will now start, and the system will write out suspended messages from both the SaveToFile procedure and the canonical SuspendedMessage message that the service creates itself.

Create Client to Edit XML in Canonical Format

The Windows service that you've created generates a new XML document according to the following XSD:

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="http://Microsoft.BizTalk.SuspendQueue.SuspendedMessage"

<xs:element name="SuspendedMessage">
       <xs:element name="Context">
             <xs:element name="ReceivedFileName" type="xs:string" />
             <xs:element name="InboundTransportLocation" type="xs:string" />
             <xs:element name="InterchangeID" type="xs:string" />
             <xs:element name="ReceivePortID" type="xs:string" />
             <xs:element name="ReceivePortName" type="xs:string" />
       <xs:element name="Message">
             <xs:element minOccurs="1" maxOccurs="unbounded"
                   <xs:element name="MessagePartId" type="xs:string" />
                   <xs:element name="Name" type="xs:string" />
                   <xs:element name="Contents" type="xs:string" />


In order to consume the XML document generated in accordance with this schema, you need to load the document into some type of editor and modify the contents of the original message contained in the <Contents> element. One option for this is InfoPath. Specifically InfoPath 2007 may be more useful because it has a Paragraph Breaks option for text boxes that allows for easier viewing of data. You may also experience problems when trying to perform changes on flat files, since most flat files use CR and LF. Flat files will need to be tested to see whether they work with this scenario.

If you are going to use InfoPath, you can easily create a new form based on the preceding schema, modify the app. config file of the Windows service to point to the processing instruction for the InfoPath form, and then be able to open the SuspendedMessage XML files that get generated. Once modified, you can just save the app.config file.

Send Document to BizTalk File Service Receive Location

The data within the <Contents> element represents the actual data for each suspended message part. Once this data has been repaired, there are two easy options for resubmitting the file:

  • Copy and paste the value within the <Contents> element into a new file within Notepad. Place this new file within the receive location drop directory to be processed by BizTalk.

  • Create a simple submit button on your InfoPath form that reads the <Contents> element and submits the file to BizTalk based upon the ReceivedFileName and InboundTransportLocation context property values.

Other -----------------
- BizTalk Server 2009 : Building a Resequencing Aggregator
- Windows Server 2003 on HP ProLiant Servers : Security Planning and Design (part 3) - Microsoft Software Update Service and Windows Update Service
- Windows Server 2003 on HP ProLiant Servers : Security Planning and Design (part 2) - Account Lockout
- Windows Server 2003 on HP ProLiant Servers : Security Planning and Design (part 1)
- Developing with SharePoint 2010 (part 4) - Developer Toolbar
- Developing with SharePoint 2010 (part 3) - Server Object Model
- Developing with SharePoint 2010 (part 2) - SharePoint Fundamentals
- Developing with SharePoint 2010 (part 1) - Platform Development Tools, Development Server Configuration
- SQL Server 2008 R2 : Creating and Managing Stored Procedures - Viewing Stored Procedures
- SQL Server 2008 R2 : Creating and Managing Stored Procedures - Deferred Name Resolution
- First look: Apple Watch

- 10 Amazing Tools You Should Be Using with Dropbox

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS
Popular keywords
HOW TO Swimlane in Visio Visio sort key Pen and Touch Creating groups in Windows Server Raid in Windows Server Exchange 2010 maintenance Exchange server mail enabled groups Debugging Tools Collaborating
Top 10
- Microsoft Excel : How to Use the VLookUp Function
- Fix and Tweak Graphics and Video (part 3) : How to Fix : My Screen Is Sluggish - Adjust Hardware Acceleration
- Fix and Tweak Graphics and Video (part 2) : How to Fix : Text on My Screen Is Too Small
- Fix and Tweak Graphics and Video (part 1) : How to Fix : Adjust the Resolution
- Windows Phone 8 Apps : Camera (part 4) - Adjusting Video Settings, Using the Video Light
- Windows Phone 8 Apps : Camera (part 3) - Using the Front Camera, Activating Video Mode
- Windows Phone 8 Apps : Camera (part 2) - Controlling the Camera’s Flash, Changing the Camera’s Behavior with Lenses
- Windows Phone 8 Apps : Camera (part 1) - Adjusting Photo Settings
- MDT's Client Wizard : Package Properties
- MDT's Client Wizard : Driver Properties
Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
2015 Camaro