Разработка распределенных приложений в Microsoft.NET Framework

         

I Администрирование каталога COM+


Текущая на момент написания курса версия .NET Framework 2.0 не содержала штатных средств администрирования каталога компонент COM+, отличных от внешней программы регистрации и удаления компонент COM+ regsvcs.exe. В частности, в библиотеке классов .NET Framework нет методов для подписки компонент на события COM+. Ниже представлено одно из возможных решений этой досадной проблемы.

Первоначально необходимо создать сборку .NET с типами из библиотеки администрирования COM и COM+, которая расположена в %systemroot%\system32\com\comadmin.dll. Это можно сделать следующими двумя командами.

sn /k comadmin.snk tlbimp %Systemroot%\system32\com\comadmin.dll /keyfile:comadmin.snk /out:interop.comadmin.dll /namespace:ComAdmin

Первая команда создает пару ключей для создаваемой сборки, вторая импортирует типы из COM библиотеки и создает подписанную сборку CLR с именем interop.comadmin.dll, включая импортированные типы в пространство имен с именем ComAdmin.

Для удобного использования классов созданной сборки interop.comadmin следует реализовать некоторый промежуточный интерфейс для администрирования каталога COM+. Данный каталог представляет собой древовидное хранилище информации о приложениях COM+, входящих в их состав компонентах и ролях пользователей. На рисунке I.I показана основная часть структуры каталога COM+, в скобках указаны имена соответствующих коллекций каталога.


Рис. I.1.  Упрощенная структура каталога COM+

Приведенные в курсе примеры используют следующий вспомогательный класс LceUtils для создания постоянной подписки. Далее идет полное описание этого класса.

// Файл SevaComLCE.cs using System; using ComAdmin; namespace Seva.ComUtils { public static class LceUtils { // Создание постоянной подписки public static void PermanentSubscription(string appName, string subscriberName, string eventGuid, string interfaceGuid) { // Создание объекта для доступа к каталогу COM+ COMAdminCatalog catalog = new ComAdmin.COMAdminCatalogClass(); ICatalogObject CatalogObject = null; ICatalogCollection CompCollection = null, SubCollection = null; // Получение списка приложений COM+ ICatalogCollection AppCollection = (ICatalogCollection) catalog.GetCollection("Applications"); AppCollection.Populate(); // Поиск нужного приложения по его имени for (int Counter = 0; Counter < AppCollection.Count; Counter++) { CatalogObject = (ICatalogObject) AppCollection.get_Item(Counter); if ((String)CatalogObject.Name == appName) { // Получение компонент приложения CompCollection = (ICatalogCollection) AppCollection.GetCollection("Components", CatalogObject.Key); CompCollection.Populate(); break; } } if (CompCollection == null) { throw new ApplicationException( String.Format("COM+ Application not found : [{0}]", appName)); } // Поиск указанной компоненты for (int Counter = 0; Counter < CompCollection.Count; Counter++) { CatalogObject = (ICatalogObject) CompCollection.get_Item(Counter); if ((String)CatalogObject.Name == subscriberName) { // Получение списка подписок компоненты SubCollection = (ICatalogCollection) CompCollection.GetCollection( "SubscriptionsForComponent", CatalogObject.Key); SubCollection.Populate(); break; } } if (SubCollection == null) { throw new ApplicationException( String.Format("Component not found : [{0}]", subscriberName)); } // Создание подписки CatalogObject = (ICatalogObject)SubCollection.Add(); CatalogObject.set_Value("EventCLSID", "{" + eventGuid + "}"); CatalogObject.set_Value("Name", "Permanent Subscription"); CatalogObject.set_Value("InterfaceID", "{" + interfaceGuid + "}"); CatalogObject.set_Value("Enabled", true); // Сохранение изменений SubCollection.SaveChanges(); } // Subscribe } //LceUtils } // Seva.ComUtils