ENTERPRISE

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

1/2/2012 11:23:27 AM

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.

Creating a New Windows Service Project and Applying Settings

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 2005.

  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.

    NOTE

    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:

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


  4. Replace "MyDrive:\MyFolder" with appropriate paths. SuspendedMessagesTempFileLocation is thelocation 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 wish to open. An example of one is

solutionVersion='1.0.0.1' productVersion='11.0.5531' PIVersion='1.0.0.0'
href='file:///C:\My%20Documents\EditAndResubmit\InfoPathForms\
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)
    Try
    ' Read the TempDirectoryName from config file
    Dim TempDirectoryName As String = _

    ConfigurationManager.AppSettings("SuspendedMessagesTempFileLocation")
    ' 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 = _
    ConfigurationSettings.AppSettings("SuspendedMessagesFileLocation")
    ' If you want to add processing instructions for InfoPath
    ' this will get it.
    Dim pi As String = _
    ConfigurationSettings.AppSettings("ProcessingInstruction")

    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()
    doc.Load(ContextFileName)

    ' Pull out context properties that you are interested in
    Dim ReceivedFileName As String = GetContextProperty(doc, _
    "ReceivedFileName")
    Dim InboundTransportLocation As String = GetContextProperty(doc, _
    "InboundTransportLocation")
    Dim InterchangeID As String = GetContextProperty(doc, _
    "InterchangeID")
    Dim ReceivePortID As String = GetContextProperty(doc, _
    "ReceivePortID")
    Dim ReceivePortName As String = GetContextProperty(doc, _
    "ReceivePortName")

    ' Create an XmlWriter to store the data.
    ' This will get written to a file when complete.
    waitingMessageFileName = [String].Format("")
    xwriter = New XmlTextWriter(waitingMessageFileName, _
    System.Text.Encoding.UTF8)
    xwriter.Formatting = Formatting.Indented
    xwriter.WriteStartDocument()
    'Write the ProcessingInstruction node.
    xwriter.WriteProcessingInstruction("mso-infoPathSolution", pi)
    xwriter.WriteProcessingInstruction("mso-application", _
    "progid=""InfoPath.Document""")
    xwriter.WriteComment(String.Format("Created on {0}", _
    DateTime.Now.ToString()))
    ' Write the context information
    xwriter.WriteStartElement("ns0", "SuspendedMessage", _


    "http://Microsoft.BizTalk.SuspendQueue.SuspendedMessage")
    xwriter.WriteStartElement("Context")
    xwriter.WriteElementString("ReceivedFileName", ReceivedFileName)
    xwriter.WriteElementString("InboundTransportLocation", _
    InboundTransportLocation)
    xwriter.WriteElementString("InterchangeID", InterchangeID)
    xwriter.WriteElementString("ReceivePortID", ReceivePortID)
    xwriter.WriteElementString("ReceivePortName", ReceivePortName)
    xwriter.WriteEndElement() ' Context
    ' Start the Message Element
    xwriter.WriteStartElement("Message")

    ' 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 = _
    doc.SelectNodes("/MessageInfo/PartInfo/MessagePart")
    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 BizTalkresources. 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"
xmlns:b=http://schemas.microsoft.com/BizTalk/2003
targetNamespace=http://Microsoft.BizTalk.SuspendQueue.SuspendedMessage
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="SuspendedMessage">
<xs:complexType>
<xs:sequence>
<xs:element name="Context"?>
<xs:complexType>
<xs:sequence>
<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:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Message">
<xs:complexType?>
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="unbounded"
name="MessagePart">
<xs:complexType>
<xs:sequence>
<xs:element name="MessagePartId" type="xs:string" />
<xs:element name="Name" type="xs:string" />
<xs:element name="Contents" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>


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 with SP1 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 2006 : Building a Resequencing Aggregator
  •  Windows System Programming : Listing Registry Keys and Contents
  •  Windows System Programming : Registry Management
  •  .NET Debugging : PowerDbg (part 2) - Send-PowerDbgCommand & Extending PowerDbg
  •  .NET Debugging : PowerDbg (part 1) - Installing PowerDbg & Analyze-PowerDbgThreads
  •  Sharepoint 2010 : Business Connectivity Services Deployment Types (part 3) - Configure Indexing & Performing a Search
  •  Sharepoint 2010 : Business Connectivity Services Deployment Types (part 2) - Creating a Profile Page to Display BCS Results
  •  Sharepoint 2010 : Business Connectivity Services Deployment Types (part 1) - Code-Based Solutions
  •  Sharepoint 2010 : BCS Architecture - Presentation & Core Components
  •  Collaborating via Web-Based Communication Tools : Evaluating Instant Messaging Services
  •  Collaborating via Web-Based Communication Tools : Evaluating Web Mail Services
  •  Developing the SAP Data Center : Data Center Physical Requirements
  •  Developing the SAP Data Center : Introducing the SAP Data Center
  •  Inventory of Broadband Phone Services
  •  Parallel Programming : Task Relationships (part 2) - Parent and Child Tasks
  •  Parallel Programming : Task Relationships (part 1) - Continuation Tasks
  •  BizTalk 2006 : Handling Ordered Delivery
  •  BizTalk 2006 : Implementing Dynamic Parallel Orchestrations
  •  Windows System Programming : The Registry
  •  Windows System Programming : File Locking
  •  
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)