Скачиваний:
100
Добавлен:
01.05.2014
Размер:
1.56 Mб
Скачать

Создание внутренних серверов и контроллеров автоматизации Внутренний сервер автоматизации и передача данных

В предыдущей главе было рассмотрено создание сервера автоматизации, выполненного в виде исполняемого файла. Однако нередко сервер автоматизации размещается в динамически загружаемой библиотеке - DLL. При обращении к такому серверу происходит загрузка библиотеки (если ранее она не была загружена) и запуск вызываемого метода.

Главное отличие сервера автоматизации в DLL заключается в том, что все объекты, содержащиеся в DLL, находятся в адресном пространстве приложения, которое к ним обращается. Поэтому сервер автоматизации, расположенный в DLL, называют внутренним или in-process-сервером, в то время как сервер, расположенный в исполняемом файле, называют локальным (out-of-process) сервером.

Внутренний сервер может манипулировать объектом, который был создан процессом в исполняемом файле, если на него передан указатель. Локальный сервер при попытке использования указателя на объект, созданный другим процессом, в лучшем случае сгенерирует сообщение об ошибке Access Violation. Для передачи указателя на объект, созданный другим процессом, необходимо использовать интерфейс IMarshall, который находит указатель на объект, созданный одним процессом в адресном пространстве другого процесса. Подробнее обIMarshallрассказывается в разделе1.7.

Создание внутреннего сервера автоматизации

Создание такого сервера всегда начинается с создания библиотеки ActiveX. Для этого необходимо выполнить команду "File/New". Затем необходимо выбрать страницу ActiveX из репозитария и на этой странице выбрать пиктограмму ÄctiveX library" (как это делалось при создании элементов управления ActiveX). Встроенный эксперт создаст новый проект. Этот проект будет генерировать код для создания DLL, при этом внешним приложениям будут видны четыре метода.

HRESULT DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID *ppv);

HRESULT DllCanUnloadNow (void);

HRESULT DllRegisterServer (void);

HRESULT DllUnregisterServer (void);

Функция DllGetClassObject создает фабрику класса CLSID и возвращает уникальный идентификатор интерфейса IID в переменной ppv приложению, вызвавшему эту функцию. ФункцияDllCanUnloadNowвызывается системой для того, чтобы установить, возможно ли выгрузить DLL из памяти и вернуть ресурсы системе, или нет (если данную DLL используют какие-либо процессы). Наконец, две последние функции используются для записи данных о сервере в системном реестре и для удаления них записей оттуда.

Затем следует вновь обратиться к пункту меню "File/New" и на странице ActiveX репозитария выбрать пиктограмму Äutomation Object". Так же как и в случае локального сервера автоматизации, появится диалог, в котором надо определить имя класса и способ создания фабрики класса при создании СОМ-объекта - будет ли создаваться новая копия (single instance), или будет возвращаться ссылка на имеющуюся копию (multiple instance). Поскольку одна DLL может обслуживать несколько приложений, выберем значение Multiple Instance. Далее следует заполнить еще два поля:

  • Threading model - определяет, каким образом будет осуществляться доступ к серверу автоматизации при работе процесса в многопоточном режиме. Эта опция имеет значение только для внутренних серверов автоматизации, поскольку локальные серверы создают свои собственные потоки. Подробно работа в многопоточном режиме обсуждается ниже. Выбор значения этого параметра никак не влияет на компилируемый код - изменяются только данные, заносимые в системный реестр;

  • Generate Event support code - поддержка нотификационных сообщений (уведомлений) от сервера автоматизации. При использовании этой опции будет создан диспинтерфейс, в котором можно определять нотификационные сообщения.

После заполнения всех полей диалога будет создана библиотека типов и модуль, где необходимо создать реализацию конкретных методов, также как и для локального сервера автоматизации. В библиотеке типов создается интерфейс, в котором следует определять свойства и методы, а так же диспинтерфейс, если реализуется поддержка нотификационных сообщений. Далее можно определить новые свойства и методы, так же как это было сделано при создании локальных серверов автоматизации.

Сервер автоматизации необходимо регистрировать в системном реестре. При этом нужно вызвать определенную ранее функцию DLLRegisterServer из какого-либо приложения. Ниже приведен фрагмент кода:

typedef HRESULT (__stdcall *DLLSERVER) (void);

...

void __fastcall TForm1::Button1Click(TObject *Sender)

{

HINSTANCE hLib;

DLLSERVER RServ;

hLib = LoadLibrary (Edit1->Text.c_str ());

if (!hLib)

{

ShowMessage ("Не могу найти библиотеку");

return;

}

RServ = (DLLSERVER) GetProcAddress (hLib, "DllRegisterServer");

if (RServ)

{

if (RServ () == S_OK)

{

ShowMessage ("Выполнена регистрация сервера.");

}

else

{

ShowMessage ("Ошибка при регистрации сервера.");

}

}

else

{

ShowMessage ("Не могу найти метод DllRegisterServer");

}

FreeLibrary (hLib);

}

В операционной системе Windows имеется приложение regsvr32.exe. При помощи этого приложения можно регистрировать внутренние серверы автоматизации в системном реестре и, наоборот, удалять сведения о них из реестра. Ниже приведены примеры соответствующих команд:

regsvr32 axstrcnt.dll - регистрация сервера

regsvr32 /u axstrcnt.ocx - удаление сервера из системного реестра