As some of you may know, Microsoft publishes an extensive documentation regarding the tasks one can perform against a BizTalk group, either throught a user interface, or through script and code. It’s called, quite ambitiously "Determining the Right Tool for your Task"!
This document is a set of matrices, grouped by relevant BizTalk artifacts they relate to. Each matrix consists in four columns and several lines, where each line lists a given potential operation you want to perform with BizTalk. The first two columns tell you what operation is available, if appropriate, through the use of the BizTalk Server Administration Console MMC Snap-In and the BizTalk Explorer user interface. More interestingly, the last two columns give you the same information when working through script and code and are of more interest to us.
If you read this list carefully, you’ll notice that certain kind of administrative tasks are only exposed from WMI. For instance, all the "Host tasks" group says in the "BizTalk Explorer Object Model" column is "None". For these tasks, you cannot rely on the neat object model exposed throught the Microsoft.BizTalk.ExplorerOM assembly.
Conversely, some operations are not available from WMI. This is why you need to use both models when working with BizTalk from code. Anyway, I don’t know about you, but I really don’t like working with WMI from C#. I find the resulting code unnecessary verbose and cumbersome. That is, until I discovered the Management Strongly Typed Class Generator command-line utility (aka MgmtClassGen).
This utility creates strongly-typed classes that alleviate the hard work usually associated with programming against WMI. For instance, take the traditional code necessary for creating a BizTalk host instance :
//Build the name of the HostInstance - name has to be in the below format string hostInstanceName = "Microsoft BizTalk Server" //Name of product + " " + hostName //Name of Host + " " + svrName; //Name of Server //Create an instance of the ServerHost class using the System.Management namespace ObjectGetOptions svrHostOptions = new ObjectGetOptions(); ManagementClass svrHostClass = new ManagementClass("root\\MicrosoftBizTalkServer" , "MSBTS_ServerHost" , svrHostOptions); ManagementObject svrHostObject = svrHostClass.CreateInstance(); //Set the properties of the ServerHost instance svrHostObject["ServerName"] = svrName; svrHostObject["HostName"] = hostName; //Invoke the Map method of the ServerHost instance svrHostObject.InvokeMethod("Map",null); //Create an instance of the HostInstance class using the System.Management namespace ObjectGetOptions hostInstOptions = new ObjectGetOptions(); ManagementClass hostInstClass = new ManagementClass("root\\MicrosoftBizTalkServer" , "MSBTS_HostInstance" , hostInstOptions); ManagementObject hostInstObject = hostInstClass.CreateInstance(); //Set the properties of the HostInstance class hostInstObject["Name"] = hostInstanceName; //Build a parameter array object  args = new object; args = uid; args = pwd; //Invoke the Install method of the HostInstance hostInstObject.InvokeMethod("Install",args);
Contrast with this code, directly taken from our BizTalk PowerShell Provider:
// map BizTalk Host ServerHost host = ServerHost.CreateInstance(); host.LateBoundObject["ServerName"] = RunningServer; host.LateBoundObject["HostName"] = HostName; host.Map(); // add new BizTalk Host Instance string name = "Microsoft BizTalk Server " + HostName + " " + RunningServer; HostInstance hostInstance = HostInstance.CreateInstance(); hostInstance.LateBoundObject["Name"] = name; hostInstance.Install(true, Credential.UserName, Credential.Password);
The difference speaks for itself, don’t you think ?
This is the approach we’ve taken in the BizTalk Powershell provider. But there’s a catch: it does work only on a local BizTalk installation. Next time, we will see how to address this issue and work against a remote installation (Thanks to Randal for pointing this out).