OLE-автоматизация для создания собственных интерфейсов
PC Magazine/RE logo
(С) СК Пресс 7/96
PC Magazine, February 6, 1996, p. 239

Заказные интерфейсы, настраиваемые объекты

Ричард Хейл Шоу


Технология OLE Automation позволяет создавать объекты, поведение которых можно программировать.

Итак, продолжим обсуждение технологии динамической компоновки и встраивания объектов (OLE). На этот раз мы отвлечемся от традиционных решений OLE, которые состоят в том, что конечные пользователи формируют сложные документы с помощью прикладных программ-контейнеров, вставляя созданные программой-сервером данные. Оставим в стороне и заложенные в программах сценарии, такие, как визуальное и "открытое" редактирование. Вместо этого мы рассмотрим такой механизм OLE, где сценарии прикладных программ не определены заранее, где ход выполнения программ не обязательно управляетс действиями конечного пользователя и где на самом деле пользовательские интерфейсы вовсе не требуются. Технология, которую мы будем изучать, называется OLE Automation (OLE-автоматизация). Благодаря этой технологии разработчики получают возможность дополнять существующие интерфейсы - а их в OLE явно недостаточно - собственными интерфейсами, которые работают в соответствии с их собственными сценариями.

Что такое автоматизация?

OLE-автоматизация - это механизм обмена информацией между процессами (interprocess communications, IPC) в среде Windows, с помощью которого одна прикладна программа или компонент может управлять другой или автоматизировать (automate) ее. Система OLE-автоматизация отличается от высокопроизводительных программ IPC, предусмотренных в Win32, поскольку она обеспечивает лишь выполнение базовых функций, позволяющих связываться и обмениваться информацией обособленным программным модулям. Задача же разработчика - назначить имена межпрограммных интерфейсов и указать способы их использования. И в то время, как высокопроизводительные программы IPC могут работать лишь с API Win32 (и следовательно, с Windows NT, Windows 95 и Win32s), система OLE-автоматов полностью совместима со всеми Windows-средами, в том числе Windows 3.1.

Почему не DDE?

Традиционно проблемы, связанные с IPC, решались в Windows с помощью динамического обмена данными (DDE). DDE - это метод обмена сообщениями, при котором одна программа (клиент DDE) может запрашивать данные у другой (сервера DDE). Существуют три основных типа транзакций или процедур DDE.

Все эти сценарии можно реализовать и с помощью средств OLE-автоматизации, причем этот путь обладает некоторыми очевидными преимуществами. Процесс автоматизированного взаимодействия между двумя обособленными программами происходит косвенно через пару посредник-заглушка (proxy-stub) компонентной модели объекта (Component Object Model, СОМ), но возможно и непосредственное соединение между клиентом-автоматом и основанным на использовании DLL рабочим (внутренним, in-process) сервером-автоматом. Средства автоматизации, как правило, работают быстрее, чем DDE, а производительность рабочих (внутренних) серверов-автоматов всегда будет превосходить производительность DDE-серверов.

Протокол DDE никогда не был хорошо документирован, и его конкретные реализации зачастую несовместимы между собой. Механизм DDE, как и многие другие компоненты Windows, был разработан группой развития пакета Excel и лишь позднее перенесен в Windows. Поэтому некоторые версии Excel - а также ряд прикладных пакетов не от Microsoft - при обращении к ним через DDE ведут себя не так, как ожидалось. Как однажды выразился внештатный редактор PC Magazine Чарлз Петцольд: "DDE - это не протокол, а исчадие ада". Поскольку система OLE Automation - это прежде всего платформа, на которой разработчик программы-сервера может строить собственные интерфейсы, а разработчик программы-клиента получать доступ к ним, она не страдает такого рода недостатками.

Интерфейс IDispatch

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

Назначение IDispatch - и, следовательно, OLE-автоматизации - позволить Windows-программам представить свои функции и данные в форме методов автоматизации и свойств, которые объединяются в логические блоки, известные как объекты-автоматы. Программа или компонент, которые предоставляют такие объекты, служат сервером-автоматом. Компонент, использующий такие объекты, называется клиентом-автоматом.

Подобно любой другой функции OLE, автоматизация не существует вне СОМ. (Дополнительные сведения можно найти в статье "OLE's Component Object Model", PC Magazine, November 21, 1995.) И, подобно любым другим функциям, она предполагает, что OLE-программы связываются и обмениваются информацией через СОМ. Следовательно, клиент-автомат будет вызывать интерфейс прикладного программирования OLE API, чтобы приказать СОМ сделать следующее.

С помощью метода IUnknown::QueryInterface клиент-автомат может получать указатели на другие интерфейсы, которые предоставляет сервер-автомат.

На этом сходство с другими элементами OLE заканчивается. Клиент-автомат может использовать метод IUnknown::QueryInterface для доступа к интерфейсу IDispatch объекта-автомата. С помощью этого интерфейса клиент-автомат может обращаться к объекту-автомату через настраиваемый интерфейс, состоящий из методов и свойств, предоставляемых сервером. Таким образом, разработчик сервера-автомата имеет возможность создавать настраиваемые интерфейсы OLE, которые можно предоставлять в распоряжение других программ или компонентов.

IDispatch в отличие от других интерфейсов OLE практически не зависит от остальных элементов OLE. Дл компонента, способного работать с IDispatch, не требуется совместимость с другими модулями OLE (кроме интерфейса IUnknown). Дополнительный обмен информацией между контейнером или клиентом и совместимым с IDispatch сервером может происходить через IDispatch. Таким образом, как только клиент-автомат получил указатель на IDispatch объекта-автомата, эти два компонента могут взаимодействовать непосредственно: OLE просто уступает дорогу. Благодаря этой независимости механизм автоматизации может применяться в прикладных программах, которые не представляют собой ни контейнеры объектов, ни серверы объектов. Конечно, наряду с этим его можно использовать для расширения возможностей контейнеров и серверов.

Пользователь располагает возможностью разработать автономную программу, которая будет играть роль сервера-автомата, предоставляя другим программам доступ к данным и функциям как к свойствам и методам,. Microsoft Excel - это пример самостоятельной прикладной программы, которая к тому же выступает в роли сервера. Сервер-автомат может размещаться и в DLL. И если дл сервера-автомата, разработанного как EXE-модуль, необходима пара посредник-заглушка, используемая в обычном механизме OLE вне процесса обмена информацией между компонентами, размещенными в обособленных адресных пространствах, то указатель IDispatch в клиенте-автомате и интерфейс IDispatch рабочего (размещенного в DLL) сервера-автомата связаны непосредственно. Поэтому, чтобы получить выигрыш в производительности, целесообразно сервер, которому нет необходимости выполняться в автономном режиме, разместить в DLL.

Использование интерфейса IDispatch

OLE-интерфейс IDispatch позволяет клиенту-автомату получать доступ к настраиваемому интерфейсу, предоставляемому сервером-автоматом (рис. 1). Клиент способен установить методы, свойства и данные объекта-автомата или определить их типы и идентификаторы (IDispatch требует, чтобы каждый метод и каждое свойство имели собственный идентификатор) и может активизировать эти методы и свойства. Это выполняется с помощью четырех функций, которые составляют данный интерфейс. GetTypeInfoCount сообщает число методов и свойств, предоставляемых сервером, а также число параметров для каждого метода. GetTypeInfo позволяет получить информацию об именах и типах каждого свойства, метода или параметра метода. Функци GetIDsOfNames в ответ на имя метода или свойства сообщает его идентификатор, а Invoke вызывает данный метод или свойство с помощью его идентификатора.

Рис. 1. Интерфейс IDispatch OLE наделен функциями, позволяющими служить платформой для предоставлени доступа к свойствам и методам, составляющим объект-автомат.
Компоненты сервера-автомата ______________________ | Определяются в OLE, | | реализуются сервером | |______________________| _____|___________________________________________ | | | | | Объект сервер-автомат | ______________|__------------ _____________________ | | GetTypeInfoCount| | | | | |_________________| | _____|______ | | ______________|_| |--->| Метод | | | | GetTypeInfo | | |____________| | | |_________________| Интерфейс | | | | ______________|_| IDispatch | | Настраиваемый | | | GetIDsOfNames | | | интерфейс | | |_________________| | _____|______ | | ______________|_| |--->| Свойство | | | | Invoke | | |____________| | | |_________________| | |_____________________| | | ------------ | | |______________________________________|__________| ________________|_________ | | Предоставляется сервером | |__________________________| Первые три функции предусматривают использование IDispatch в динамическом режиме. Предположим, что клиент-автомат "знает" имена и типы данных свойств, методов и параметров методов, но ему не известны их идентификаторы. Например, типичная программа на языке Visual Basic (VB) может вызывать метод объекта-автомата. Однако эта программа знает только им метода, но не его идентификатор. Поэтому для получени идентификатора компилятор VB вызывает функцию IDispatch::GetIDsOfNames сервера, чтобы обратиться к методу. В действительности компилятор даже не знает, верно ли указано имя метода, предполагает, что программист назвал имя правильно. Но транслятор - он VB может в динамическом режиме проверить существование конкретного свойства, метода или параметра метода с помощью IDispatch.

Благодаря наличию динамического режима можно отложить обращение к серверу для проверки идентичности и типов свойств, и методов объектов-автоматов данного сервера во время разработки. На самом деле устраняетс даже необходимость в том, чтобы сервер был установлен в системе разработчика. Динамический режим IDispatch также позволяет клиенту во время выполнения принимать решения о том, какие свойства и методы использовать, хотя это не обязательно. И Visual Basic, и Excel по умолчанию применяют IDispatch в динамическом режиме.

IDispatch также можно использовать в статическом режиме, т. е. с помощью библиотеки типов (type library) - файла, в котором описываются специальные свойства и методы, предоставляемые объектом-автоматом. Библиотека типов может быть составлена разработчиком сервера-автомата. Она предоставляет имена, типы и идентификаторы методов и свойств, чтобы разработчик клиента-автомата мог встроить эту информацию в свое программное изделие. Когда информация о типах уже известна, клиент-автомат способен просто активизировать методы и свойства в объекте-автомате, не запрашивая эти сведения у сервера. Возможность обращаться к библиотеке типов и применять IDispatch в статическом режиме появилась только в версии 4.0 компилятора VB, тогда как и в Excel, и в Visual C++ это было осуществимо всегда.

Главное преимущество статического применени IDispatch - увеличение производительности. Без библиотеки типов автомат-клиент должен запрашивать у сервера подтверждение имен и типов свойств и методов объекта-автомата и определять их идентификаторы. Но, когда информация из библиотеки типов введена в текст программы, клиент легко может получить непосредственный доступ к свойствам и активизировать методы: исключаетс необходимость предварительно запрашивать сервер. Таким образом, хотя при статическом применении IDispatch необходимо затратить больше усилий на разработку, клиенту-автомату, использующему библиотеку типов, во время исполнения приходится только однократно активизировать объект сервера-автомата для обращения к методу или свойству. При динамическом же применении IDispatch клиент вынужден вызывать объект по меньшей мере дважды: один раз для проверки имени метода или свойства и получения соответствующего идентификатора, а второй раз для собственно активизации свойства или метода.

Различия в производительности не столь велики дл внутренних (DLL) серверов, но для локальных (EXE) серверов этот дополнительный обход границы процесса может дорого стоить, если не сказать больше. Таким образом, отсутствие бибиотеки типов в очередной новой версии сервера следует рассматривать как недобросовестность поставщика.

Автоматизация в сети

Существует одна область, где DDE имеет явное преимущество перед OLE Automation: работа в сети. Сетевые средства DDE применяются уже не первый день (по крайней мере, с момента появления Windows for Workgroups), в то время как сетевой механизм OLE Automation официально еще не признан. Предполагается, что сетевые средства автоматизации появятся как компонент системы Distributed OLE, отдельные элементы которой войдут в следующую редакцию Windows NT (неофициально называемую NT 4.0) в апреле 1996 г. Distributed OLE предусматривает использование той же самой пары посредник-заглушка, которая соединяет клиентов и EXE-серверы, работающие в различных адресных пространствах. Но в этом случае можно с тем же успехом связывать клиентов и серверы, исполняемые на разных машинах.

Однако, согласно информации на конец 1995 г., сетевая автоматизация с помощью Distributed OLE будет применима только к EXE-серверам. Причина состоит в том, что без EXE-модуля, загружающего внутренний (размещаемый в DLL) сервер-автомат, последний не может быть загружен для обеспечения работы клиента-автомата - как в сети, так и на одной машине. Пока неясно, занимается ли группа OLE компании Microsoft поисками приемлемого (т. е. безопасного и надежного) решени проблемы внутренних серверов, работающих в удаленном режиме, или же только намеревается делать это. Поэтому в настоящее время планы по сетевым компонентам-автоматам не предусматривают использование серверов-автоматов, размещаемых в DLL.

Временным решением проблемы может стать технология, которая позволяет реализовать OLE Automation в сети. Под давлением некоторых крупных корпоративных заказчиков группе Visual Basic компании Microsoft пришлось разработать механизм Remote Automation (дистанционной автоматизации), который позволяет выполнять любой внешний сервер-автомат на удаленной системе. Remote Automation также будет работать с внутренним сервером-автоматом - в случае если последний вызывается внешним сервером из той же самой системы. Внешний сервер использует механизм Remote Automation для подключения к клиенту и формирования промежуточного слоя между клиентом и удаленным внутренним сервером. Remote Automation будет работать с любой парой автоматов клиент-сервер, причем они не обязательно должны быть написаны на языке Visual Basic. Технологи Remote Automation совместима с такими основными сетевыми протоколами, как Internet, IPX, Named Pipes, NetBEUI и TCP/IP при условии, что серверы размещаются в системах, работающих под управлением Windows NT или Windows 95 (клиент может работать под управлением Windows NT, Windows 95 или даже Windows 3.1).

Поскольку в Remote Automation используется тот же самые двоичные интерфейсы, что и в OLE Automation, она будет работать с существующими компонентами-автоматами сразу после ее инсталляции. Следовательно, пара автоматов клиент-сервер может быть спроектирована, разработана, проверена и отлажена на одной машине, а затем перенесена на удаленную систему. Для реализации соединения с автоматом-сервером удаленной системы в Remote Automation обычная пара посредник-заглушка заменена новыми модулями, которые используют стандартный протокол Remote Procedure Calls (RPC, вызовы удаленных процедур) для обмена информацией по сети. Модуль, играющий роль посредника, работает в системе клиента и использует RPC для передачи запросов клиента и данных компоненту, имеющему название Automation Manager, который выполняется в удаленной системе с сервером и имитатором заглушки (рис. 2). Automation Manager использует модуль, играющий роль заглушки, для преобразования запросов от посредника в вызовы удаленного сервера. Клиент работает с имитатором посредника точно так же, как и с посредником-оригиналом, а программа Automation Manager скрыта от удаленного сервера, поскольку между ними размещается имитатор заглушки. Automation Manager использует модули, заменяющие посредника и заглушку, чтобы управлять передачей параметров между компонентами точно так же, как это делала бы традиционная пара посредник-заглушка. Ни клиент, ни сервер "не знают", что они работают в удаленном режиме. А поскольку Automation Manager создает отдельный поток для работы с каждым клиентом, он может обслуживать запросы нескольких клиентов, не снижая производительности сервера.

Рис. 2. В системе Remote Automation традиционна пара посредник-заглушка заменена модулями, позволяющими локальному клиенту-автомату связыватьсы с удаленным сервером.
Remote Automation ПК клиента | ПК сервера ---------- | ---------- _______________ ________________ | | Удаленный | | Клиент-автомат | | ______________ | сервер | |________________| | | COM/RA | | (EXE) | | | | __________ | | ___________ | | _______________ | | | Заглушка |---->---| Удаленный | | | | COM/RA | | | |__________| | | | объект | | | | ___________ | | |______________| | |___________| | | | | Посредник | | | | |_______________| | | | | | удаленного| | | ___|__________ ->---| объекта |<--------->| Automation | | |___________| | | \ | Manager | --------------- | \ |______________| | \ | Процедуры дистанционного | вызова в паре посредник-заглушка К сожалению, специалисты из группы OLE компании Microsoft рассматривают Remote Automation главным образом как временное ухищрение, потому что это только первый шаг, не обеспечивающий безопасности и устойчивости, которые будут заложены в Distributed OLE. Но корпоративные разработчики часто находят такие решения целесообразными и полезными, в особенности если они изначально понимают, что это лишь краткосрочное временное решение. А Remote Automation - определенно временное решение.

В любом случае применение технологии Remote Automation сейчас - и Distributed OLE, когда она появится, - позволит разработчикам решать ряд проблем, связанных с программным обеспечением, такими способами, которые осуществимы только лишь при наличии нескольких компьютеров. Например, в сетевой машине вычисления, требующие интенсивного использования аппаратных средств, и занимающий продолжительное время поиск в базах данных можно переложить на вторичную систему, предоставляя большую свободу первичной системе пользователя. Разработчик может также использовать сервер Remote Automation, чтобы построить более ясный и изящный интерфейс со сложным механизмом сервера (подобно SQL-процессору) или встроить бизнес-правила в интерфейс удаленного сервера.

С момента своего появления OLE Automation механизм автоматизации был, пожалуй, наиболее трудной дл понимания и вызывающей несправедливые нарекания частью OLE. На самом же деле вину за незаслуженные упреки в адрес OLE Automation следует возложить на тех сотрудников корпорации Microsoft, которые заявляют, что единственное назначение этой технологии - обеспечение совместимости с макроязыками, применяемыми дл разработки прикладных программ. Действительно, с помощью макроязыка типа Visual Basic for Application (VBA) корпорации Microsoft можно относительно легко обеспечить взаимодействие между клиентом-автоматом и сервером-автоматом. Но совместимость с макроязыками - это только вершина айсберга тех возможностей, которые предоставляет автоматизация, и те, кто расхваливает только одно это измерение данной технологии, оказывают ей плохую услугу.

Ричард Хейл Шоу - внештатный редактор PC Magazine.