Шаг 316.
Создание внутрипроцессных серверов автоматизации. Внутрипроцессный сервер автоматизации (общие сведения)

    На этом шаге мы рассмотрим основные шаги, выполняемые для создания такого сервера.

    Как мы уже говорили в пердыдущих шагах, нередко сервер автоматизации создается в виде DLL. Главное отличие такого сервера автоматизации заключается в том, что все объекты, содержащиеся в DLL, находятся в адресном пространстве приложения, которое к ним обращается. Поэтому сервер автоматизации, расположенный в DLL, называют внутрипроцессным сервером, в то время как сервер, расположенный в исполняемом файле, называют внепроцессным сервером.

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

    Указатель невозможно передать через стандартные переменные: в языке IDL и в спецификации, описывающей правила создания серверов и контроллеров автоматизации, отсутствует переменная типа pointer. Однако можно передать переменную типа Integer, затем преобразовать ее к типу pointer и манипулировать этим объектом. Пример передачи указателя через переменную типа Integer приведен в следующих шагах.

    Создание внутрипроцессного сервера автоматизации всегда начинается с создания библиотеки ActiveX. Для этого необходимо выбрать команду File | New | Other, перейти на страницу ActiveX репозитария объектов и выбрать значок ActiveX library (как это делалось при создании элементов управления ActiveX).


Рис.1. Выбор ActiveX library

    Встроенный мастер создаст новый проект:

library Project1;

uses
  ComServ;

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

{$R *.RES}

begin
end.

    Этот проект будет генерировать код для создания DLL, причем внешним приложениям будут видны четыре функции. Реализация этих функций приведена в модуле ComServ. Следующая функция создает фабрику классов для данного идентификатора класса (CLSID) и возвращает уникальный идентификатор интерфейса (IID) в переменной Obj приложению, вызвавшему эту функцию:

  DllGetClassObject(const CLSID, IID: TGUID: var Obj): HRESULT;

    Другая функция вызывается операционной системой для того, чтобы установить, можно или нет выгрузить DLL из памяти и вернуть ресурсы операционной системе (если данную библиотеку используют какие-либо процессы):

  DllCanUnloadNow: HRESULT;

    Наконец, две последние функции требуются для записи данных о сервере в системном реестре и для удаления этих записей оттуда.

    Обратите внимание на то, что программисту не следует писать код реализации этих функций, так как он уже содержится в модуле ComServ. Если же необходимо эти функции переопределить, то можно написать их реализацию, но она обязана включать все то, что имеется в реализации ComServ, и список формальных параметров этих функций должен быть тем же самым, что и в ComServ.

    Затем следует вновь обратиться к команде File | New | Other и на странице ActiveX репозитария выбрать значок Automation Object.


Рис.2. Выбор Automation Object

    Так же как и в случае внепроцессного сервера автоматизации, появится диалоговое окно, в котором следует определить имя класса и способ создания фабрики классов при создании СОМ-объекта - будет ли создаваться новая копия (Single Instance) или будет возвращаться ссылка на имеющуюся копию (Multiple Instance).


Рис.3. Окно Automation Object Wizard

    Поскольку одна библиотека может обслуживать несколько приложений, выберем значение Multiple Instance.

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

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

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

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

type
  TDLLRegisterServer=function: HResult; stdcall;

procedure TForm1.RegisterServerClick(Sender: TObject);
var
  LibName:string;
  HLib:THandle;
  RServ:TDLLRegisterServer;
begin
  LibName:=Edit1.Text; // Имя библиотеки
  HLib:=LoadLibrary(pchar(LibName));
  if HLib<>0 then begin
    RServ:=GetProcAddress(HLib,'DllRegisterServer');
    if Assigned(RServ) then begin
      if RServ=S_OK then 
      ShowMessage(Format('Серве %s успешно '+
      ' зарагистрирован',[LibName]))
      else ShowMessage(Format('Ошибка при регистрации сервера %s',
           [LibName]));
    end else ShowMessage('Метод DllRegisterServer '+
        ' в данной библиотеке не найден');
    FreeLibrary(HLib);
  end else ShowMessage(Format('Библиотека %s не найдена',
           [LibName]));
end;

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

    При регистрации COM DLL в системном реестре в секции InProcServer32 описывается модель потоков, если в раскрывающемся списке Threading model не выбран пункт None.

    На следующем шаге мы рассмотрим обработку ошибок.




Предыдущий шаг Содержание Следующий шаг