OLE-автоматизация для создания собственных интерфейсов
Технология 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.
Традиционно проблемы, связанные с IPC, решались в Windows с помощью динамического обмена данными (DDE). DDE - это метод обмена сообщениями, при котором одна программа (клиент DDE) может запрашивать данные у другой (сервера DDE). Существуют три основных типа транзакций или процедур DDE.
Протокол DDE никогда не был хорошо документирован, и его конкретные реализации зачастую несовместимы между собой. Механизм DDE, как и многие другие компоненты Windows, был разработан группой развития пакета Excel и лишь позднее перенесен в Windows. Поэтому некоторые версии Excel - а также ряд прикладных пакетов не от Microsoft - при обращении к ним через DDE ведут себя не так, как ожидалось. Как однажды выразился внештатный редактор PC Magazine Чарлз Петцольд: "DDE - это не протокол, а исчадие ада". Поскольку система OLE Automation - это прежде всего платформа, на которой разработчик программы-сервера может строить собственные интерфейсы, а разработчик программы-клиента получать доступ к ним, она не страдает такого рода недостатками.
В отличие от других систем OLE - например, традиционного механизма динамической компоновки объектов, где разработчик должен строить заранее определенные интерфейсы, работающие в соответствии с заранее разработанными сценариями, управляемыми пользователем, - OLE Automation требует только одного OLE-интерфейса: IDispatch. Для этого интерфейса не нужно никаких заранее установленных сценариев - он позволяет компоненту определять настраиваемый интерфейс, которым может беспрепятственно воспользоваться другой OLE-компонент.
Назначение IDispatch - и, следовательно, OLE-автоматизации - позволить Windows-программам представить свои функции и данные в форме методов автоматизации и свойств, которые объединяются в логические блоки, известные как объекты-автоматы. Программа или компонент, которые предоставляют такие объекты, служат сервером-автоматом. Компонент, использующий такие объекты, называется клиентом-автоматом.
Подобно любой другой функции OLE, автоматизация не существует вне СОМ. (Дополнительные сведения можно найти в статье "OLE's Component Object Model", PC Magazine, November 21, 1995.) И, подобно любым другим функциям, она предполагает, что OLE-программы связываются и обмениваются информацией через СОМ. Следовательно, клиент-автомат будет вызывать интерфейс прикладного программирования OLE API, чтобы приказать СОМ сделать следующее.
На этом сходство с другими элементами OLE заканчивается. Клиент-автомат может использовать метод IUnknown::QueryInterface для доступа к интерфейсу IDispatch объекта-автомата. С помощью этого интерфейса клиент-автомат может обращаться к объекту-автомату через настраиваемый интерфейс, состоящий из методов и свойств, предоставляемых сервером. Таким образом, разработчик сервера-автомата имеет возможность создавать настраиваемые интерфейсы OLE, которые можно предоставлять в распоряжение других программ или компонентов.
IDispatch в отличие от других интерфейсов OLE практически не зависит от остальных элементов OLE. Дл компонента, способного работать с IDispatch, не требуется совместимость с другими модулями OLE (кроме интерфейса IUnknown). Дополнительный обмен информацией между контейнером или клиентом и совместимым с IDispatch сервером может происходить через IDispatch. Таким образом, как только клиент-автомат получил указатель на IDispatch объекта-автомата, эти два компонента могут взаимодействовать непосредственно: OLE просто уступает дорогу. Благодаря этой независимости механизм автоматизации может применяться в прикладных программах, которые не представляют собой ни контейнеры объектов, ни серверы объектов. Конечно, наряду с этим его можно использовать для расширения возможностей контейнеров и серверов.
Пользователь располагает возможностью разработать автономную программу, которая будет играть роль сервера-автомата, предоставляя другим программам доступ к данным и функциям как к свойствам и методам,. Microsoft Excel - это пример самостоятельной прикладной программы, которая к тому же выступает в роли сервера. Сервер-автомат может размещаться и в DLL. И если дл сервера-автомата, разработанного как EXE-модуль, необходима пара посредник-заглушка, используемая в обычном механизме OLE вне процесса обмена информацией между компонентами, размещенными в обособленных адресных пространствах, то указатель IDispatch в клиенте-автомате и интерфейс IDispatch рабочего (размещенного в DLL) сервера-автомата связаны непосредственно. Поэтому, чтобы получить выигрыш в производительности, целесообразно сервер, которому нет необходимости выполняться в автономном режиме, разместить в DLL.
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.