Managing Remote BizTalk Groups with WMI

Last week, we’ve seen how to leverage strongly-typed management classes in order to manage BizTalk groups. But, as hinted towards the end of the post, the code shown only worked for local installations of BizTalk and did not allow accessing remote instances.

In fact, it turns out that the generated code makes provision for this scenario via the StaticScope property. This static property allows to override the default WMI scope used to instantiate the management objects.

StaticScope Property

The StaticScope property takes a string that must adhere to the following syntax:

\\<hostname>\<namespace>:<classname>>.<property>=’<value>

What is cumbersome, is to have to specify the name of the WMI class in the property. By looking at the code, one can find that this name is already available to the generated class, through its private CreatedClassName field. Therefore, I find it easier to encapsulate the creation of the scope string into a helper class that retrieves the value of this private field through reflection, like so:

        internal static class ManagementScopeHelper
            {
                private static string SCOPE_TEMPLATE
                    = @"\\{1}\root\MicrosoftBizTalkServer:{0}.MgmtDbNameOverride='{2}'";

                public static ManagementScope GetScope(Type type, string instance, string database)
                {
                    string classname = GetCreatedClassName(type);
                    string scope =
                        String.Format(SCOPE_TEMPLATE, classname, instance, database);

                    return new ManagementScope(scope);
                }

                private static string GetCreatedClassName(Type type)
                {
                    return (string)
                        type.GetField(
                            "CreatedClassName"
                                , BindingFlags.NonPublic | BindingFlags.Static)
                                    .GetValue(null);
                }
            }
        }

With this helper snippet, the resulting code for accessing a remote BizTalk group in order to create a new host instance is slightly modified like so:

        try
        {
            // map BizTalk Host

            ServerHost.StaticScope = ManagementScopeHelper.GetScope(typeof(ServerHost), server_, database_);
            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.StaticScope = ManagementScopeHelper.GetScope(typeof(HostInstance), server_, database_);
            HostInstance hostInstance = HostInstance.CreateInstance();
            hostInstance.LateBoundObject["Name"] = name;
            hostInstance.Install(true, Credential.UserName, Credential.Password);
    }

    finally
    {
        HostInstance.StaticScope = null;
        ServerHost.StaticScope = null;
    }

Even though this might not be strictly necessary, I like wrapping the code into a try/finally block so as to make sure the function does not have any unspecified side effect in the presence of raised exceptions. I think this is important for libraries and frameworks designed to be used by third-party code (which is the case for the BizTalk Factory Automation Layer).

This entry was posted in WMI. Bookmark the permalink.