ServicesResourcesConferencesOur TeamWeblogsAboutContact
   
Enterprise Service Application reconfiguration

I'm currently writing an application which needs to support various scenarios for automatic reconfiguration of Enterprise Service properties. In essence, the application should expose a ServicedComponent which provides methods to dynamically reconfigure itself and its hosting application. I just thought that maybe someone else might be interested in a step-by-step explanation about how to do this:

My first step was to extend AssemblyInfo.cs to include some constants which will be used to generate the COM+ application ID and name:

using System.Reflection;
using System.Runtime.CompilerServices;
using System.EnterpriseServices;

[assembly: ApplicationActivation(ActivationOption.Library)]
[assembly: ApplicationName(MyApplicationInfo.COMPLUS_APP_NAME)]
[assembly: ApplicationID(MyApplicationInfo.COMPLUS_APP_GUID)]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyKeyFile(@"..\..\..\perfkey.snk")]

public class MyApplicationInfo
{
   public const string COMPLUS_APP_GUID=  "{E678632B-5F9C-4d9b-B204-61E14D4BE913}";
   public const string COMPLUS_APP_NAME=  "Some Demo Application";
}

I then generated a strongly-named interop wrapper for ComAdmin by running:

tlbimp c:\windows\system32\com\comadmin.dll 
     /asmversion:1.0.0.0 /keyfile:perfkey.snk /sysarray

The COMAdmin components allow you to directly access and modify settings of your Enterprise Service components, like security, transactions, activation, and so on. I used GetCollection("Application") and PopulateByKey(...) to load the information for my own application. (Note: If you have the VS.NET 2003 MSDN Library installed, you can find more information about the properties which can be configured at here and (for settings pertinent to applications) here. After changing any properties, you have to call SaveChanges() on the collection object.

using System;
using System.EnterpriseServices;
using COMAdmin;

public class TestConfigurator: ServicedComponent
{
   private ICatalogCollection GetMyInformation() 
   {
      COMAdminCatalog cat = new COMAdmin.COMAdminCatalog();
      object[] queries = new object[1];
      queries[0] = MyApplicationInfo.COMPLUS_APP_GUID;
      Array arr = (Array) queries;
      cat.Connect("localhost");
      COMAdminCatalogCollection apps = 
           (COMAdminCatalogCollection) cat.GetCollection("Applications");
      apps.PopulateByKey(arr);

      if (apps.Count==0)
      {
         throw new Exception("COM+ Application '" + 
             MyApplicationInfo.COMPLUS_APP_NAME + "' not found.");
      }

      return apps;
   }

   public void DisableAuthentication()
   {
      ICatalogCollection apps = GetMyInformation();
      ICatalogObject myApp = (ICatalogObject) apps.get_Item(0);
      myApp.set_Value("Authentication", 
          COMAdminAuthenticationLevelOptions.COMAdminAuthenticationNone);
      apps.SaveChanges();
   }

   public void EnableAuthentication()
   {
      ICatalogCollection apps = GetMyInformation();
      ICatalogObject myApp = (ICatalogObject) apps.get_Item(0);
      myApp.set_Value("Authentication",
          COMAdminAuthenticationLevelOptions.COMAdminAuthenticationDefault);
      apps.SaveChanges();
   }

   public void SwitchToLibraryActivation()
   {
      ICatalogCollection apps = GetMyInformation();
      ICatalogObject myApp = (ICatalogObject) apps.get_Item(0);
      myApp.set_Value("Activation", "Inproc");
      apps.SaveChanges();
   }

   public void SwitchToServerActivation()
   {
      ICatalogCollection apps = GetMyInformation();
      ICatalogObject myApp = (ICatalogObject) apps.get_Item(0);
      myApp.set_Value("Activation", "Local");
      apps.SaveChanges();
   }
}

These settings will be applied immediately for the next component activation (i.e. "SomeServicedComponent x = new SomeServicedComponent()"). If your E/S application for example contains an additional component MyTestComponent, you can run client-side code like the following to test both activation scenarios:

class clientApp
{
   static void Main(string[] args)
   {
      TestConfigurator cnf = new TestConfigurator();

      MyTestcomponent tst = new MyTestcomponent();
      // the following will be executed in library-activation (in-process)
      tst.DoSomething();

      Console.WriteLine("Switching to Server-Activation");
      cnf.SwitchToServerActivation();
      tst = new MyTestcomponent();
      // the following will be executed in server-activation 
      // (out of process)
      tst.DoSomething();

      Console.WriteLine("Switching back to Library-Activation");
      cnf.SwitchToLibraryActivation();
      tst = new MyTestcomponent();
      // the following will again be executed in library-activation mode 
      // (in-process)
      tst.DoSomething();

      Console.WriteLine("Done");
      Console.ReadLine();
   }
}

Quite nice, isn't it?

posted on Monday, May 24, 2004 2:54 PM

Powered by Community Server, by Telligent Systems