Export (0) Print
Expand All

BizTalk Server 2002 WMI Programming in Microsoft .NET Framework

Click here to download sample - BizTalkNetWMILib.exe.
 

Peishu Li, Senior BizTalk Architect
Microsoft Corporation

May 2002

Applies to:
   Microsoft® .NET Framework
   Microsoft BizTalk® Server 2002
   Microsoft Visual Studio® .NET

Summary: How to use WMI programming techniques for BizTalk Server 2002 in the Microsoft .NET Framework. (24 printed pages)

Download BizTalkNetWMILib.exe.

Contents

Introduction
WMI Architecture
Programming WMI for BizTalk Server 2002 in the .NET Framework
   Enumerating Management Objects
   Retrieve a Management Object
   Creating a New Management Object
   Deleting a Management Object
   Executing Methods on a Management Object
   Monitoring Management Events
   Using WMI Extensions for VS.NET Server Explorer
BizTalk Server 2002 WMI Class Library for .NET
   Design Considerations
   The Base Class
   The Derived Classes
   Sample Applications
Conclusion

Introduction

Microsoft® BizTalk® Server 2002 uses Microsoft Windows® Management Instrumentation (WMI) for its administrations. The BizTalk Administration MMC snap-in that ships with BizTalk Server 2002 is a WMI application that enables you to perform BizTalk Server administration tasks through WMI. In this article, you will learn how to program WMI for BizTalk Server 2002 in Microsoft .NET Framework, including using the classes in the System.Management namespace of the .NET. You will see how to build a reusable .NET class library so that average developers can use it to access BizTalk Server 2002 administration functionality in the .NET Framework without having to learn the complexity of WMI programming.

This article assumes that you are familiar with BizTalk Server 2002 environment, especially the BizTalk Server Administration tool. It is also assumed that you have a basic understanding of the Microsoft .NET Framework and are familiar with Microsoft Visual Studio® .NET, including Microsoft Visual C#™ .NET and Microsoft Visual Basic® .NET.

WMI Architecture

Windows Management Instrumentation (WMI) is the Microsoft implementation of the industry standard, Web-Based Enterprise Management (WBEM), an initiative of Desktop Management Task Force (DMTF). WMI provides a consistent and richly descriptive model of the configuration, status, and operational aspects of Windows platforms. It simplifies the task of developing well-integrated management applications and provides scalable, effective enterprise management solutions. WMI has been integrated with Microsoft management products, such as Microsoft System Management Server, Microsoft Operations Manager and Microsoft Application Center for managing configurations, operations, monitoring system health and so on. Figure 1 illustrates the architecture of WMI.

Ee251573.bts_wmiprogramming_01(en-US,BTS.10).gif

Figure 1. The three-tiered architecture of WMI

As shown in Figure 1, WMI uses a three-tiered approach for collecting and distributing data, based on the Common Information Model (CIM) schema:

  • Management applications—This is the client tier that consists of management applications that consume WMI data through appropriate WMI interfaces. Traditionally, Windows management applications access WMI data through either the IWbem COM interface or the SWbemScripting automation interface. In the Microsoft .NET Framework, the System.Management namespace enables developers to write .NET applications (Windows Forms or Web Forms/ASP.NET Pages) through .NET managed code.
  • The WMI infrastructure—This is the middle tier in which the CIM manager gathers management data from appropriate WMI providers and makes them available to management applications through appropriate interfaces. The CIM object repository stores object definitions and schemas. The CIM object manager is a key component that provides a collection and manipulation point for managed objects.
  • WMI providers—In this tier, WMI providers act as data access API for accessing underlying instrumentation data (managed objects). Microsoft Windows Platform SDK includes a set of WMI providers such as Registry Provider, Windows NT Event Log Provider, Win32 Provider, SNMP Providers, and WDM Provider. BizTalk Server 2002 ships with a BizTalk WMI provider that enables you to access BizTalk Server instrumentation data (stored in BizTalk Messaging Management and Shared Queue databases) through WMI.

It is important to understand that in the WIM architecture, the tiers are loosely coupled in which management applications (WMI consumers) and WMI providers are independent of each other. You can develop management applications using either traditional WMI APIs (COM or scripting) or the .NET WMI Client API (the System.Management namespace) to consume WMI data, regardless of the technologies that were used to provide the WMI data.

Programming WMI for BizTalk Server 2002 in the .NET Framework

BizTalk Server 2002 provides the following sixteen WMI classes for managing receive functions, shared queues and performing other administration tasks such as managing BizTalk server, server groups, managing the BizTalk Messaging Management database, and so on:

  • MicrosoftBizTalkServer_Server
  • MicrosoftBizTalkServer_GroupServer
  • MicrosoftBizTalkServer_Group
  • MicrosoftBizTalkServer_ReceiveFunction
  • MicrosoftBizTalkServer_GroupReceiveFunction
  • MicrosoftBizTalkServer_Queue
  • MicrosoftBizTalkServer_SuspendedQueue
  • MicrosoftBizTalkServer_WorkQueue
  • MicrosoftBizTalkServer_RetryQueue
  • MicrosoftBizTalkServer_ScheduledQueue
  • MicrosoftBizTalkServer_MgmtDB
  • MSBTS_CustomCounter
  • MSBTS_CustomCounterSetting
  • DocSuspendedEvent
  • ReceiveFunctionDisabledEvent
  • InterchangeProvError
Note   Detailed information about these classes including their methods and/or properties can be found in BizTalk Server 2002 product documentation.

To program WMI for BizTalk Server 2002 in the .NET Framework, you need to access these classes using the System.Management namespace. First you will need to add a reference to your Visual Studio .NET IDE (Visual Basic .NET or Visual C# project). To do this, right click the References node in the Solution Explorer and select Add Reference. In the Add Reference dialog box, select System.Management in the .NET tab and click the Select button. Click OK. This will add the System.Management namespace reference to your project, as shown in Figure 2.

Ee251573.bts_wmiprogramming_02(en-US,BTS.10).gif

Figure 2. Adding the System.Management namespace to a Visual Studio .NET project

You need also add the following line in the code:

Visual C# .NET

using System.Management;

Visual Basic .NET

Imports System.Management

Now we are going to demonstrate some basic WMI programming techniques in .NET Framework for BizTalk Server 2002. We illustrate both C# and Visual Basic .NET code. For simplicity, we stripped out the exception management code.

Enumerating Management Objects

To return a list of management objects (receive functions, for example), you create a ManagementObjectSearcher object, which takes two parameters in the constructor:

  • A ManagementScope object for specifying the scope of management operations, for BizTalk Server 2002, you always pass "\\MachineName\root\MicrosoftBizTalkServer" to the constructor. For local machine, the syntax is "\root\MicrosoftBizTalkServer"
    Note   For C#, you need to escape the "\" character so the syntax is "\\\\MachineName\\root\\MicrosoftBizTalkServer" unless you use the @ prefix for a literal string, for example, @"\\MachineName\root\MicrosoftBizTalk".
  • A WqlObjectQuery object, which takes a WQL statement in its constructor. To return a list of a particular WMI class, the WQL statement is "Select * from WMI_ClassName".

The Get method of the ManagementObjectSearcher object returns a ManagementObjectCollection object, which contains a collection of ManagementObject. You can use the foreach block in C# or the For Each. . .Next block in Visual Basic .NET to enumerate the collection.

The code snippet below demonstrates how to return a list of receive functions and iterate the list and write the name of each receive function to the system console.

C#

string strWQL = "Select * from MicrosoftBizTalkServer_ReceiveFunction";
ManagementObjectSearcher searcher = new ManagementObjectSearcher (
    new ManagementScope("root\\MicrosoftBizTalkServer"),
    new WqlObjectQuery(strWQL));
foreach (ManagementObject obj in searcher.Get())
{
    Console.WriteLine(obj["Name"]);
}

Visual Basic .NET

Dim strWQL As String 
strWQL = "Select * from MicrosoftBizTalkServer_ReceiveFunction"
Dim searcher As New ManagementObjectSearcher( _
    New ManagementScope("root\MicrosoftBizTalkServer"), _
    New WqlObjectQuery(strWQL))
Dim obj As ManagementObject
For Each obj in searcher.Get()
    Console.WriteLine(obj("Name"))
Next obj

Retrieve a Management Object

To return a specific management object, you create a new ManagementObject object instance and specify its Scope and Path properties with a ManagementScope object and ManagementPath object, respectively. The ManagementPath object provides a wrapper for parsing and building paths to WMI objects. Its constructor takes a string parameter for specifying the object path. For example, "WMI_ClassName.Name='NameOfTheManagedObject'". The Get method of the ManagementObject object will return the specified managed object, if it exists.

The following code snippet demonstrates how to return a file receive function named "Csharp File Receive Function" and write its channel name to the system console.

C#

ManagementObject obj = new ManagementObject();
obj.Scope = new ManagementScope("root\MicrosoftBizTalkServer");
string strPath = "MicrosoftBizTalkServer_ReceiveFunction.Name="
    + "'CSharp File Receive Function'";
obj.Path = new ManagementPath(strPath);
obj.Get();
Console.WriteLine(obj["ChannelName");

Visual Basic .NET

Dim obj As New ManagementObject()
obj.Scope = New ManagementScope("root\MicrosoftBizTalkServer")
Dim strPath As String
strPath = "MicrosoftBizTalkServer_ReceiveFunction.Name=" _
    + "'CSharp File Receive Function'"
obj.Path = New ManagementPath(strPath)
obj.Get()
Console.WriteLine(obj(["ChannelName"))

Creating a New Management Object

To create a new management object and save it, follow these steps:

  1. Create a new ManagementObjectScope object and call its Connect method.
  2. Create a new ManagementPath object.
  3. Create a new ManagementClass object and call its CreateInstance method to return a ManagementObject object.
  4. Set the properties of the ManagementObject object.
  5. Call the Put method and specify the PutType.CreateOnly enumeration to save the newly created managed object.

The following example demonstrates how to create a new file receive function named "Csharp File Receive Function".

C#

// create the ManagementObjectScope object and get connected
ManagementObjectScope scope =
   new ManagementScope("root\\MicrosoftBizTalkServer");
scope.Connect();

// create the MangementPath object
string strPath = "MicrosoftBizTalkServer_ReceiveFunction";
ManagementPath path = new ManagementPath(strPath);

// create a ManagementClass object and spawn a ManagementObject
  instance
ManagementClass cls = new ManagementClass(scope, path, null);
ManagementObject obj = cls.CreateInstance();

// set the properties for the ManagementObject
obj["Name"] = "CSharp File Receive Function";
obj["GroupName"] = "BizTalk Server Group";
obj["ProcessingServer"] = "PLI"; //change to your server name
obj["ProtocolType"] = 1; //File receive function
obj["PollingLocation"] = "C:\\Temp\\DataIn";
obj["FilenameMask"] = "*.xml";
obj["Username"] = "";
obj["Password"] = "";
obj["OpennessFlag"] = 1; //BIZTALK_OPENNESS_TYPE_NOTOPEN
obj["ChannelName"] = "Channel_Test";

// save the ManagementObject
obj.Put(PutType.CreateOnly);

Visual Basic .NET

' create the ManagementObjectScope object and get connected
Dim scope As New ManagementScope("root\MicrosoftBizTalkServer")
scope.Connect()

' create the MangementPath object
Dim strPath As String
StrPath = "MicrosoftBizTalkServer_ReceiveFunction"
Dim path As New ManagementPath(strPath)

' create a ManagementClass object and spawn a ManagementObject instance
Dim cls As New ManagementClass(scope, path, Nothing)
Dim obj As ManagementObject
obj = cls.CreateInstance()

' set the properties for the ManagementObject
obj("Name") = "CSharp File Receive Function"
obj("GroupName") = "BizTalk Server Group"
obj("ProcessingServer") = "PLI" 'change to your server name
obj("ProtocolType") = 1 'File receive function
obj("PollingLocation") = "C:\Temp\DataIn"
obj("FilenameMask") = "*.xml"
obj("Username") = ""
obj("Password") = ""
obj("OpennessFlag") = 1; 'BIZTALK_OPENNESS_TYPE_NOTOPEN
obj("ChannelName") = "Channel_Test"

' save the ManagementObject
obj.Put(PutType.CreateOnly)

Deleting a Management Object

To delete a management object, you simply call the Delete method of the ManagementObject, as illustrated in the following code snippet, which deletes a file receive function:

C#

ManagementObject obj = new ManagementObject();
obj.Scope = new ManagementScope("root\\MicrosoftBizTalkServer");
string strPath = "MicrosoftBizTalkServer_ReceiveFunction.Name='"
    + "CSharp File Receive Function'";
obj.Path = new ManagementPath(strPath);
obj.Delete();

Visual Basic .NET

Dim obj As New ManagementObject()
obj.Scope = New ManagementScope("root\MicrosoftBizTalkServer")
Dim strPath As String
strPath = "MicrosoftBizTalkServer_ReceiveFunction.Name='" _
    + "CSharp File Receive Function'"
obj.Path = New ManagementPath(strPath)
obj.Delete()

Executing Methods on a Management Object

To execute a method on a WMI class, you call the overloaded method of the ManagementObject, InvokeMethod. The basic syntax is:

C#

outparams =  obj.InvokeMethod("MethodName", inparams, options);

Visual Basic .NET

outparams =  obj.InvokeMethod("MethodName", inparams, options)

Where in outparams is a ManagementBaseObject, which contains an array of output parameters and a return value (if any). The inparams is also a ManagementBaseObject, which enables you to pass input parameters to the method. The obj is a ManagementObject and the options is InvokeMethodOptions class that inherits ManagementOptions class.

The code snippet below demonstrates how to invoke the Resubmit method of the MicrosoftBizTalkServer_SuspendedQueue class. Later in this article, you will see some examples that process the output parameters when we discuss the BizTalk Server 2002 Class Library for .NET.

C#

string strWQL = "Select * from MicrosoftBizTalkServer_SuspendedQueue";
ManagementObjectSearcher searcher = new ManagementObjectSearcher (
    new ManagementScope("root\\MicrosoftBizTalkServer"),
    new WqlObjectQuery(strWQL),
    null);
foreach (ManagementObject obj in searcher.Get())
{
    obj.InvokeMethod("Resubmit", null, null);
}

Visual Basic .NET

Dim strWQL As String
StrWQL = "Select * from MicrosoftBizTalkServer_SuspendedQueue"
Dim searcher As New ManagementObjectSearcher ( _
    New ManagementScope("root\MicrosoftBizTalkServer"), _
    New WqlObjectQuery(strWQL), _
    Nothing)
Dim obj As ManagementObject
For Each obj in searcher.Get()
    obj.InvokeMethod("Resubmit", Nothing, Nothing)
Next obj

Monitoring Management Events

BizTalk Server 2002 fires two types of management events through respective WMI classes:

  • DocSuspendedEvent—An event will be fired whenever a document ends up in the SuspendedQueue (excluding those documents that are removed to the Suspended queue from other Shared queues such as the Work queue, the Retry queue, and the Scheduled queue).
  • ReceiveFunctionDisabledEvent—An event will be fired whenever a receive function is disabled.

The following code excerpt illustrates the basic steps for monitoring the document suspended events:

  1. Create a WqlEventQuery object (similar to the creation of a WqlObjectQuery object).
  2. Create a ManagementEventWater object and pass the WqlEventQuery object to the constructor.
  3. Call the WaitForNextEvent method of the ManagementEventWater object that returns a ManagementBaseObject (this can be done in a loop for monitoring ongoing events).
  4. Process the ManagementBaseObject in response to the event.
  5. Optionally, cancel the event subscription.

C#

using System;
using System.Management;

public class SuspendedQueueEvent {
   public static int Main(string[] args) {
      // create a query object for watching for suspended document events
      WqlEventQuery eventQuery = 
          new WqlEventQuery("select * from DocSuspendedEvent");

      // initialize an event watcher
      ManagementEventWatcher watcher = new ManagementEventWatcher
        (query);

      // waite for the next suspended document event occurs
      ManagementBaseObject e = watcher.WaitForNextEvent();

      // display the GUID of the suspended document
      Console.WriteLine("Docment suspened : " + 
        e["stringSuspendedGuid"]);

      // cancel the subscription
      watcher.Stop();
      return 0;
    }
}

Visual Basic .NET

Imports System
Imports System.Management

Public Class SuspendedQueueEvent
   Overloads Public Shared Function Main(args() As String) As Integer
      ' create a query object for watching for suspended document events
      Dim query As New WqlEventQuery("select * from DocSuspendedEvent")

      ' initialize an event watcher
      Dim watcher As New ManagementEventWatcher(query)

      ' waite for the next suspended document event occurs
      Dim e As ManagementBaseObject = watcher.WaitForNextEvent()

      ' display the GUID of the suspended document
      Console.WriteLine("Docment suspened : " + e("stringSuspendedGuid"))

      ' cancel the subscription
      watcher.Stop()
      Return 0
   End Function 'Main
End Class 'SuspendedQueueEvent

Note   The above code sample only illustrates the simplest way for consuming WMI events. A more robust implementation would be using delegates to consume WMI events asynchronously. In the code download for this article, you can find a Visual C# project solution file, SQWatcherService.sln, which is a Windows service application that monitors the document suspended events. When a document is suspended, this Windows service will send an e-mail message according to the recipient specified in the application configuration file, App.config.

Using WMI Extensions for VS.NET Server Explorer

Visual Studio .NET introduces the Server Explorer, a server management console through which you can do things such as opening data connections and logging on to servers and exploring their databases and system services. The Server Explorer also supports drag-and-drop operations so that you can drag certain nodes in the Server Explorer and drop them onto Visual Studio .NET designers to create pre-configured components such as a new data component.

The WMI Extensions for VS.NET Server Explorer adds two new nodes to the Server Explorer to provide WMI functionality, Management Classes and Management Events, as shown in Figure 3 (you can display the Server Explorer in the Visual Studio .NET IDE by clicking View|Server Explorer menu options).

Ee251573.bts_wmiprogramming_03(en-US,BTS.10).gif

Figure 3. Two WMI extensions (nodes) were added to the Server Explorer.

To add a WMI class into the Server Explorer, right click the Management Classes node and select Add Classes to bring up the Add Classes dialog box. The Available classes list on the left displays the available WMI classes on the server you are connected to. To add a BizTalk WMI class to the Server Explorer, expand the root\MicrosoftBizTalkServer node to display its classes and then highlight the class you wanted to add (for example, MicrosoftBizTalkServer_SuspendedQueue) and click the Add> button to add it to the Selected classes list on the right. Click OK to close the Add Classes dialog box. The new node with the name of the BizTalk WMI class should be added under the Management Classes node, as shown in Figure 4.

Ee251573.bts_wmiprogramming_04(en-US,BTS.10).gif

Figure 4. A MicrosoftBizTalkServer_ReceiveFunction WMI class was added to the Server Explorer.

You can use this new WMI class in the Server Explorer to automatically generate a WMI wrapper class. For example, you can right click the MicrosoftBizTalkServer_ReceiveFunction node and select Generate Managed Class. The Visual Studio .NET IDE will generate a .cs or .vb class file, depending on the project type you are working on (Visual C# .NET or Visual Basic .NET project). The generated class is an early-bound wrapper of the underlying WMI object.

The following code snippet illustrates how to retrieve a receive function and displays the name of its associated channel to the system console, very similar to the code you saw earlier using the raw WMI Client API:

C#

ManagementScope scope =
    new ManagementScope("root\\MicrosoftBizTalkServer");
string strPath = 
    "MicrosoftBizTalkServer_ReceiveFunction.Name=" 
    + "'CSharp File Receive Function'";
ManagementPath path = new ManagementPath(strPath);
ReceiveFunction rf = new ReceiveFunction(scope,path);
Console.WriteLine(rf.ChannelName);

Visual Basic .NET

Dim scope As New ManagementScope("root\\MicrosoftBizTalkServer")
Dim strPath As String 
strPath = "MicrosoftBizTalkServer_ReceiveFunction.Name=" _
    + "'CSharp File Receive Function'"
Dim path As New ManagementPath(strPath)
Dim rf As New ReceiveFunction(scope,path)
Console.WriteLine(rf.ChannelName)

You may have noticed the early-bounding syntax rf.ChannelName in the above code snippet versus the late-bounding rf["ChannelName"] or rf("ChannelName") syntax you used in the raw WMI API code. This is one of the advantages of using the Server Explorer WMI extension. The following code snippet further demonstrates early-bounding, which allows you to use strong-typed object ReceiveFunction instead of the generic type ManagementObject.

C#

Foreach(ReceiveFunction rf in ReceiveFunction.GetInstances())
{
    Console.WriteLine(rf.ChannelName);
}

Visual Basic .NET

Dim rf As ReceiveFunction
For Each rf in ReceiveFunction.GetInstances()
    Console.WriteLine(rf.ChannelName);
Next rf

Note   In addition to using the Server Explorer WMI extension, you can also manually generate the strong-typed wrapper classes by one of the following means, both are documented in Microsoft .NET Framework SDK:
  • Executing the MgmtClassGen.exe utility from the command line.
  • Calling the GetStrongTypedClassCode of the ManagementClass object.

BizTalk Server 2002 WMI Class Library for .NET

So far we have introduced some basic WMI programming techniques for BizTalk Server 2002 in the .NET environment. Using these techniques requires knowledge of both BizTalk Server 2002 WMI classes and the .NET System.Management namespace. These learning curves can prevent an average BizTalk developer from being productive. It would be good to encapsulate the complexity of WMI programming into some high level and reusable .NET classes so that the average BizTalk developer can use them as they would any regular .NET classes.

For example, instead of writing a dozen lines of code to create a new file receive function, as you saw in the section Create a New Management Object, you may simply do this:

ReceiveFunction rf = new ReceiveFunction(this.txtBizTalkServer.Text);
rf.CreateFileReceiveFunction(
    "CSharp File Receive Function",
    "BizTalk Server Group",
    this.txtBizTalkServer.Text,
    "C:\\Temp\\DataIn",
    "*.xml",
    "Channel_Test");

Note   We broke the second line of code into multiple lines to improve readability.

The BizTalk Server 2002 WMI Class Library for .NET is a single assembly DLL that makes up all the necessary .NET classes that encapsulate the entire functionality of BizTalk Server 2002 WMI API and expose them as task-oriented high level APIs, as in the previous example.

Design Considerations

Due to the language neutral characteristics of the .NET Framework, you can implement a .NET class library in any .NET language. We've chosen C# language to build the BizTalk Server 2002 WMI Class Library for .NET because C# is the only .NET language today that supports XML documentation, a key feature for implementing a class library. This greatly simplifies the process of creating technical documentation for the users of the class library.

The class library groups BizTalk Server 2002 management functionalities into nine classes. Each class corresponds to a specific type of administration object in BizTalk Server 2002 (a receive function, a Suspended queue item, and so forth). All of these classes are derived from a single base class. This design leverages the inheritance feature of the C# programming language to promote code reuse. To that end, instead of being an abstract class, the base class actually carries implementations.

The Base Class

All the non-private members (properties and methods) in the base class, BTSWMILibBaseClass, are marked as protected to prevent them from being called directly by a client application. The following table describes the members of the base class. A derived class may implement one or more members of the base class.

Table 1. Members of the Basic ClassBTSWMILibBaseClass

Class MemberDescription
BizTalkServerNamespaceThis is a read-only property, which provides a convenient means for the derived classes to retrieve the BizTalk Server namespace, in the form of "\\\\ServerName\\root\\MicrosoftBizTalkServer".
GetManagementObjectCollectionThis method returns a ManagementObjectCollection that is a collection of a specific ManagementObject, for example, a collection of receive functions, or Suspended queue items, and so forth, depending on the type of the derived class.
GetDataSetThis method returns a list of management object in a form of ADO.NET DataSet instead of a ManagementObjectCollection, making it ideal for populating data aware controls (for example, the DataGrid control) in management applications.
GetAllThis is an alternate method to GetManagementObjectConnection.
GetByNameThis method returns a ManagementObject specified by a name.
DeleteThis is an overloaded method, which allows you to delete a ManagementObject you are currently working on (such as a SuspendedQueue item) or a named ManagementObject (such as a receive function).
MoveToSuspendedQWe include this method in the base class based on the consideration that three of the functional classes (WorkQueue, RetryQueue, and ScheduledQueue) need to implement a MoveToSuspendedQueue method.

Most of the methods in the base class were implemented using the techniques you learned in the previous section of this article. The GetDataSet method deserves some extra explanation. This method returns an ADO.NET DataSet object to facilitate a management client application to consume the collection of managed objects and bind them to data-aware controls such as a DataGrid.

You can populate a DataSet object by one of the two means:

  • Using existing data from a database through the DataAdapter object.
  • Creating a DataSet object, add a DataTable object, and populate the DataTable object with appropriate data from any data sources.

In the GetDataSet method, we used the second approach. The method iterates the returned ManagementObjectCollection (via the Get method of the ManagementObjectSearcher) two times to build the DataSet object and its associated DataTable object.

In the first iteration, the foreach block, we defined the structure of the DataTable for the DataSet, as illustrated below:

foreach (ManagementObject obj in searcher.Get())
{
    string strBaseName = GetBaseName(this.m_strNamespace);
    tb = ds.Tables.Add(strBaseName);

    foreach(PropertyData p in obj.Properties) 
    {
    DataColumn col = tb.Columns.Add(p.Name, typeof(string));
    if (p.Name=="Name")
        {
        tb.PrimaryKey = new DataColumn[] {col};
        }
    }
    break;
}

We specified the element name using the GetBaseName function (a helper function that is declared as private and static in the base class). For example, in the case of receive function (MicrosoftBizTalkServer_ReceiveFunction namespace), the element name is "btswmi_receivefunctions". Inside the nested foreach loop, we set the column name as the name of the property, using the PropertyData object. We also set the "Name" property as the primary key of the DataTable. Notice the break keyword used in the outer foreach loop. It ensures that we only iterate the collection once for getting the metadata, setting up column names and primary key for the DataTable object.

In the second foreach block of the GetDataSet method, we populated each row in the DataTable with the value of each property and then appended the row to the DataTable through the Add method:

foreach (ManagementObject rf in searcher.Get())
{
    DataRow row = tb.NewRow();
    foreach(PropertyData p in rf.Properties)
    {
        row[p.Name] = p.Value;
    }
    tb.Rows.Add(row);
}

Finally, the GetDataSetMethod returns the DataSet object to the client:

Return ds;

The GetDataSetMethod is inherited in several derived classes. You will see how to execute these inherited methods in client applications later in this article.

The Derived Classes

The BizTalk Server 2002 WMI Class Library for .NET contains the nine classes that are derived from base class, BTSWMILibBaseClass. The following table summarizes these classes and their methods:

Table 2. The Derived Classes in BizTalk Server 2002 WMI Class Library for .NET

ClassesMethods
ReceiveFunctionReceiveFunctions

DataSetReceiveFunctions

GetAllReceiveFunctions

GetReceiveFunctionByName

CreateFileReceiveFunction

CreateMSMQReceiveFunction

CreateHTTPReceiveFunction

DeleteReceiveFunction

SuspendedQueueSuspendedQueueItems

DataSetSuspendedQueueItems

GetSuspendedDocument

GetErrorDescription

Resubmit

DeleteSuspendedItem

XXXQueueXXXQueueItems*

DataSetXXXQueueItems*

MoveToSuspendedQueue

ServerServers

DataSetServers

GetAllServers

GetServerByName

CreateServer

DeleteServer

StartServer

FreeInterchanges

GroupGroups

DataSetGroups

GetGroupByName

CreateGroup

DeleteGroup

PurgeSuspendedQueue

RefreshParserListFromRegistry

BTMDatabaseCreateBTMDatabase

GetBTMDatabase

CustomCounterCreateCustomCounter

GetCustomCounterByName

DeleteCustomCounter

ValidateCustomCounter

GetMatchCount

*XXXQueue stands for WorkQueue, RetryQueue, and ScheduledQueue.

All the derived classes, except for the BTMDatabase class, directly inherited one or more of the five methods of the base class (GetManagementObjectCollection, GetDataSet, GetByName, and Delete). For example, the ReceiveFunction class implemented all these five methods in a similar fashion:

base.MethodName();

Whereas the XXXQueue classes all implemented a MoveToSuspendedQueue method by extending the MoveToSuspendeQ method of the base class:

base.MoveToSuspendedQ(obj);

where obj is a ManagementObject representing a XXXQueue.

Note   Passing the WMI class name (for example, the MicrosoftBizTalkServer_ReceiveFunction) in the constructor of the derived class to the base class makes it possible for the generic methods of the basic class to be extended in the derived class.

The derived classes may also implement some specific methods that are not found in the base class. These methods fall into two categories:

  • The first category contains the CreateXXX methods (for example, CreateFileReceiveFunction, CreateServer, CreateGroup, CreateCustomCounter, and so on), which used the techniques as described in the Creating a New Management Object section to create an appropriate WMI managed object.
  • The second category includes methods such as Resubmit, StartServer, StopServer, and so on. These methods wrapped the InvokeMethod method to call the execute methods of the underlying managed object, as we introduced in the Executing Methods on a Management Object section. The ValidateCustomCounter method of the CustomCounter class demonstrated how to process output parameters of an InvokeMethod method call, using a ManagementBaseObject:
    public void ValidateCustomCounter(
        ManagementObject obj, 
        ref bool bIsValidSrcOrg,
        ref bool bIsValidSrcId,
        ref bool bIsValidDestOrg,
        ref bool bIsValidDestId,
        ref bool bIsValidGroup)
    {
        try
        {
            ManagementBaseObject OutParams =
                obj.InvokeMethod("IsValid",null,null);
    
            bIsValidSrcOrg = (bool)OutParams["bIsValidSrcOrg"];
            bIsValidSrcId = (bool)OutParams["bIsValidSrcId"];
            bIsValidDestOrg = (bool)OutParams["bIsValidDestOrg"];
            bIsValidDestId = (bool)OutParams["bIsValidDestId"];
            bIsValidGroup = (bool)OutParams["bIsValidGroup"];
        }
        catch (Exception e)
        {
            throw new Exception(e.Message,e);
        }
    }
    
    

Sample Applications

The BizTalk Server 2002 WMI Class Library can be consumed by any .NET language. The sample code download associated with this article contains two client applications, one for C# and another for Visual Basic .NET. Figure 5 shows a screenshot of the C# client application.

Click here for larger image

Figure 5. The C# Client Application (click thumbnail for larger image)

To use the class library in Visual Studio .NET, you need to set a reference to the BTSWMILib.dll assembly and specify it in the code:

C#

using MSDN.BTSWMILib;

Visual Basic .NET

Imports MSDN.BTSWMILib

A feature of the class library is that some of the classes return an ADO.DataSet object instead of a ManagementObjectCollection, making it ideal for displaying the results in a DataGrid control for both Windows applications and ASP.NET applications, as illustrated in the following code snippet:

C#

ReceiveFunction rf = new ReceiveFunction(this.txtBizTalkServer.Text);
DataSet ds = rf.DataSetReceiveFunctions();
DataTable tb = ds.Tables["btswmi_receivefunctions"];
this.dgBTSWMILib.DataSource = tb;
this.dgBTSWMILib.Refresh();

Visual Basic .NET

Dim rf As New ReceiveFunction(Me.txtBizTalkServer.Text)
Dim ds As DataSet
ds = rf.DataSetReceiveFunctions()
Dim tb As DataTable
tb = ds.Tables("btswmi_receivefunctions")
Me.dgBTSWMILib.DataSource = tb
Me.dgBTSWMILib.Refresh()

For comparison purposes, also included is sample code in the client applications that process the ManagementObjectCollection and display them in the DataGrid control.

Conclusion

The loosely coupled architecture of WMI and the System.Management namespace in the Microsoft .NET Framework makes it possible to write pure .NET managed code that accesses WMI functionality exposed by any WMI providers, without using any interoperating wrappers.

In this article, we demonstrated how to write .NET code that accesses BizTalk Server 2002 WMI classes. We also introduced a reusable .NET class library written in C# that encapsulates the complexity of WMI programming and exposes BizTalk Server 2002 WMI functionality as a set of high-level .NET classes. BizTalk developers without WMI programming skills can use these classes in their own .NET applications, as they would any regular .NET classes.

About the author

Peishu Li is a BizTalk expert and the author of the book, BizTalk Server Developer's Guide by Osborne/McGraw Hill. Peishu has implemented numerous large-scale BizTalk and .NET solutions in legal, banking, and telecommunication industries. He has also developed many custom components, adapters, and utilities for facilitating the development, deployment, operation, and administration of BizTalk Server. Peishu can be reached via email at pli@wt.net.

Show:
© 2014 Microsoft