Приложение I. Администрирование каталога COM+
Приложение 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+, в скобках указаны имена соответствующих коллекций каталога.
Приведенные в курсе примеры используют следующий вспомогательный класс 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
