Save BizTalk Messages in C# .Net using PowerShell and BizTalkOperations Class - Part 2

In the last post on this topic I left off at the point where the GetAndSaveMessagesWithOperations method still needed to be defined. This method is basically the DoWork() of the whole process. It takes in Message Box database name and as well as an instance ID and gets all the messages associated to that.

You may notice that this solution is actually a hybrid of the first couple of methods outlined by Thiago Almeida in his blog post about programatically saving BizTalk messages.

The first part is the "get" of messages. It reads the registry to check what the names of databases are, then creates a BizTalkOperations object using those values. Finally a service instance is grabbed.

public static void GetAndSaveMessagesWithOperations(string instanceID, string path, string messageBoxDBName)
        Guid instanceGUID = new Guid(instanceID);

        RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\BizTalk Server\3.0\Administration");
        string mgmtDBServer = (string)registryKey.GetValue("MgmtDBServer");
        string mgmtDBName = (string)registryKey.GetValue("MgmtDBName");
        BizTalkOperations ops = new BizTalkOperations(/*SQL Server:*/ mgmtDBServer, /*Mgmt DB:*/ mgmtDBName);
        MessageBoxServiceInstance mbsi = ops.GetServiceInstance(instanceGUID);

        bool exists = Directory.Exists(path);
        if (!exists)

        SaveMessagesWithOperations(messages: mbsi.Messages, instanceID: instanceID, DBServer: mgmtDBServer, messageBoxDBName: messageBoxDBName, dirPath: path);

The messages from that instance are then passed to the method which actually saves them to disk.

    public static void SaveMessagesWithOperations(IEnumerable messages, string instanceID, string DBServer, string messageBoxDBName, string dirPath)
        string body = string.Empty;

        foreach (BizTalkMessage msg in messages)
            MessageBoxDatabase mbdb = new MessageBoxDatabase(DBServer, messageBoxDBName);
            BizTalkOperations operations = new BizTalkOperations();
            IBaseMessage message = operations.GetMessage(msg.MessageID, msg.InstanceID, mbdb);

            StringBuilder sb = new StringBuilder();

            // some messages are just the routing failure ones that we don't care about.
            if (message.BodyPart != null)
                using (StreamReader streamReader = new StreamReader(message.BodyPart.Data))
                    body = streamReader.ReadToEnd();

                string messageType = string.Empty;
                messageType = (string)message.Context.Read("MessageType", "");

                if (messageType != null)
                    messageType = messageType.Split('#')[1];
                    messageType = "MLLP";

                // using variable so I can look at it in debugging
                string filePath = dirPath + @"\"                        
                    + messageType + "_"
                    + ((Microsoft.BizTalk.Operations.BizTalkMessage)(message)).CreationTime.ToString("yyyyMMdd_HHmmss") + "_"
                    + message.MessageID.ToString() + "_"
                    + instanceID 
                    + ".xml";


This is basically just a giant barf of all the suspended messages regardless of type. I created this in somewhat of an emergency/learning situation, so it's not exactly pretty. I was able to save them all, sort by the file name to find all the messages types I wanted (hence the messageType prefixing the filename).

I've been meaning to refactor some of this to make it more efficient and possibly even more dynamic, but figured posting it first might even result in ideas coming my way as to how to make it better.