Using WMI to Monitor Send Ports and Receive Locations in BizTalk Server

The question has come up more than a couple of times: How do I monitor my Send Ports or Receive Locations if I don't have MOM (or monitoring solution of your choice) configured for my BizTalk servers?  I've always been positive the answer was in WMI, so I finally decided to see if I could write a very basic port monitor for BizTalk.

First, I needed to build the WMI queries, using the WqlEventQuery class.  Most of the WMI-specific classes mentioned here are in the System.Management namespace.  Full source code is available at the end of the article.

 WqlEventQuery wqlSendPortEventQuery = new WqlEventQuery(
    "__InstanceModificationEvent", 
    new TimeSpan(0, 0, 10), // poll every 10 sec
    "TargetInstance isa \"MSBTS_SendPort\"");
WqlEventQuery wqlReceiveLocationEventQUery = new WqlEventQuery(
    "__InstanceModificationEvent",
    new TimeSpan(0, 0, 10),
    "TargetInstance isa \"MSBTS_ReceiveLocation\"");

Next I had to configure a ManagementEventWatcher for Send Ports and Receive Locations:

 ManagementEventWatcher wmiSendPortEvents = new ManagementEventWatcher(
    new ManagementScope(@"\\.\root\MicrosoftBizTalkServer"),
    wqlSendPortEventQuery);
ManagementEventWatcher wmiReceiveLocationEvents = new ManagementEventWatcher(
    new ManagementScope(@"\\.\root\MicrosoftBizTalkServer"),
    wqlReceiveLocationEventQuery);

Then an event handler for each watcher:

 wmiReceiveLocationEvents.EventArrived += 
    new EventArrivedEventHandler(WmiEventReceived);
wmiSendPortEvents.EventArrived += 
    new EventArrivedEventHandler(WmiEventReceived);

Finally, I fire them up:

 Console.WriteLine("Starting event watchers...");
wmiReceiveLocationEvents.Start();
wmiSendPortEvents.Start();
Console.WriteLine("Event watchers started.  Press ENTER to exit...\r\n");

The event handler itself is where things got somewhat complicated, because the event itself doesn't contain the BizTalk-specific properties I'm interested in.  So I had to dig a little.  In this case, we're only interested in the TargetInstance:

 static void WmiEventReceived(object sender, EventArrivedEventArgs e)
{
    ManagementBaseObject evt = e.NewEvent;
    PropertyDataCollection col = evt.Properties;
    PropertyDataCollection.PropertyDataEnumerator en = col.GetEnumerator();

    while (en.MoveNext())
    {
        PropertyData data = en.Current;

        // Grab TargetInstance only (could use PreviousInstance to get prior state data) :
        if(data.Value != null && data.Name == "TargetInstance")
        {
            ManagementBaseObject mbo = (ManagementBaseObject)data.Value;
            if (mbo.ClassPath.ClassName == "MSBTS_SendPort") // Send port event
            {
                ROOT.MICROSOFTBIZTALKSERVER.SendPort.ManagementSystemProperties prop = new SendPort.ManagementSystemProperties(mbo);
                int iSendPortStatus = Convert.ToInt32(mbo.Properties["Status"].Value.ToString());
                Console.WriteLine("Server: {0}", prop.SERVER);
                Console.WriteLine("Send Port Name: {0}", mbo.Properties["Name"].Value.ToString());
                Console.WriteLine("Send Port Status: {0}", GetSendPortStatusString(iSendPortStatus));
            }
            else if (mbo.ClassPath.ClassName == "MSBTS_ReceiveLocation") // Receive location event
            {
                ROOT.MICROSOFTBIZTALKSERVER.ReceiveLocation.ManagementSystemProperties prop = new ReceiveLocation.ManagementSystemProperties(mbo);
                bool isDisabled = true;
                bool.TryParse(mbo.Properties["IsDisabled"].Value.ToString(), out isDisabled);
                Console.WriteLine("Server: {0}", prop.SERVER);
                Console.WriteLine("Receive Location Name: {0}", mbo.Properties["Name"].Value.ToString());
                Console.WriteLine("Receive Port Name: {0}", mbo.Properties["ReceivePortName"].Value.ToString());
                Console.WriteLine("Receive Location Status: {0}", GetReceiveLocationStatusString(isDisabled));
            }
        }
    }
    Console.WriteLine("");
}

In case you're wondering, the ROOT.MICROSOFTBIZTALKSERVER classes are generated from the Management Classes in the Visual Studio Server Explorer.  See this article for more details.

So, how does it look?

PortMonitor

So from here you can do anything with these events that you'd like.  I supposed you could even have the event handler generate a message that you send to BizTalk... as long as the port doesn't go down. =)

Source code:

 

Technorati Tags: BizTalk,WMI

Comments

  • Anonymous
    April 23, 2008
    Hi Chris, when I run the application, I get in the console watcher waiting.I drop messages in several receive locations but nothing happens.Thanks for your help
  • Anonymous
    April 23, 2008
    The program will monitor the status of the port (enabled/disabled), not the traffic through the port.To test the application, start the console app and then disable or unenlist a port.Feel free to email me (email button at top of page) if you need clarification.
  • Anonymous
    June 23, 2008
    Nice Article!What is the minimun permissions set required to make it works? What services (EntSSo,...)does it depends on?
  • Anonymous
    July 10, 2008
    The comment has been removed
  • Anonymous
    November 18, 2009
    The comment has been removed
  • Anonymous
    February 08, 2010
    Great Article!This is big! Thanks a lot for having this article.In my organization we are going to use WCF-SQL adapter and since we have a BizTalk that has two BizTalk Server(for now) then we have to handle the concurrency. I think one solution is to cluster the receive location host instance but unfortunately windows clustering is not an option for us right now so we've decided we're just going to disable the other host instance. supposed to be it will be a manual disaster recovery but i have this idea to create a windows service that will monitor host instance to automatically enable the other host instance once problem was encountered. I think it's a nice solution but since i found this wmi event then it will be even more better.have you thought of this idea of enabling another hostinstance of the same BizTalk Group once the other hostinstance once disable? do you foresee any issue for this? I would appreciate if you could let me know.Thanks a lot!