Об системно-объектной модели SOM, на которой основана оболочка OS/2
Оболочка Workplace Shell OS/2 основывается на мощной системно-объектной модели.
Технология объектно- ориентированного программирования сулит много преимуществ не только программистам, но и конечным пользователям. И далеко не последнее из них - возможность создавать прикладные программы из готовых модулей. Если вам до сих пор не доводилось сталкиваться с OS/2, вы можете не знать, что Workplace Shell (оболочка рабочего места) представляет собой объектно-ориентированный комплекс и что все ее объекты - папки, блокноты, принтеры, шаблоны и т.п. - суть готовые компоненты, которые вы можете настраивать и интегрировать в свои прикладные программы.
Оболочка Workplace Shell (WPS) основана на системно-объектной модели (System Object Model - SOM) IBM - технологии, специально разработанной для решени таких проблем, как жесткая привязка объектов к их клиентам и необходимость использования одного и того же языка программирования. Объекты Workplace Shell работают в среде SOM, доступ в которую можно реализовать почти на всех языках программирования, где предусмотрены внешние процедуры, в том числе и на REXX. Хотя с помощью REXX невозможно создать класс WPS или разбить его на подклассы - для этого вам понадобитс отдельный компилятор SOM,- вы тем не менее можете создавать и уничтожать объекты WPS и выполнять практически все остальные операции с ними. Такие возможности приходятся очень кстати, если вы системный администратор, которому нужно кофигурировать несколько рабочих станций.
SOM - не связанная ни с одним конкретным языком объектно-ориентированная технология для создания, хранения и использования двоичных бибилиотек классов. Ключевые слова здесь "двоичные" и "не связанная ни с одним конкретным языком". Хотя многие считают OS/2 технологией прошлого, модель SOM на самом деле представляет собой одну из наиболее интересных новых разработок в области компьютерной индустрии на сегодняшний день. Объектно-ориентированное программирование (ООП) заслужили безоговорочное признание в качестве основной парадигмы, однако его применению в коммерческом программном обеспечении препятствуют отсутствие в языках ООП средств дл обращения к библиотекам классов, подготовленным на других языках, и необходимость поставлять с библиотеками классов исходные тексты. (Многим независимым разработчикам библиотек классов приходитс продавать заказчикам исходные тексты, поскольку разные компиляторы по-разному отображают объекты.)
Как мы увидим в дальнейшем, SOM снимает и эти ограничения, и те, что налагаются жесткой привязкой объекта к его клиентам на уровне двоичных кодов, которая выступает помехой для многих языков ООП - таких как C++, - где сообщения и методы связываютс статически во время компиляции, а не во врем выполнения. Кроме того SOM представляет интерес не только для разработчиков OS/2. В настоящее время среда выполнения SOM поставляется в комплекте OS/2, и системы AIX корпорации IBM, особо продается версия для Windows. Архитектура составных документов OpenDoc, используема Apple, также основана на SOM. Настоящий потенциал SOM заключается в ее совместимости практически с любой платформой и любым языком программирования. SOM соответствует спецификации COBRA (Common Object Request Broker Architecture - Архитектура посредника стандартного объектного запроса), которая определяет стандарт условий взаимодействия между прикладными программами в неоднородной сети.
Спецификация COBRA была разработана консорциумом Object Management Group (Группа управления объектами), объединяющим более 300 компаний - поставщиков программного обеспечения и оборудования и потребителей их продукции. В консорциум входят все основные компьютерные фирмы, что определяет ее значительное влияние. Даже корпорация Microsoft - член консорциума, хотя ее участие находится под вопросом, так как она занимается разработкой своего собственного стандарта - Модели составных объектов (Component Object Model - COM), - который по всей видимости со временем составит конкуренцию COBRA.
Спецификация COBRA является частью более широкого стандарта для распределенной обработки, называемого Архитектурой управления объектами (Object Management Architecture - OMA). COBRA определяет архитектуру Посредника объектного запроса (Object Request Broker - ORB), который управляет взаимодействием между объектами и прикладными программами. Через ORB можно посылать запросы между процессами, работающими на одной машине, или между машинами в сети. DSOM (Distributed SOM) - структура распределенных объектов SOM, входящая в пакет SOMObjects Developer Toolkit, поставляемый IBM, - представляет собой реализацию COBRA ORB.
Все вышесказанное означает, что SOM, или точнее DSOM, - достаточно перспективная технология для работы с распределенными объектами и проявление общей тенденции в компьютерной индустрии к более тесному сотрудничеству. Многие считают спецификацию COBRA единственным действительно работоспособным стандартом, связывающем различные платформы и операционные системы. И SOM - достойная реализация этого стандарта, которую вы можете использовать уже сегодня.
SOM - это объектная модель, которая имеет структуру классов и предоставляет механизм для независимой разработки библиотек классов на разных языках программирования и для отделения реализации класса от клиентских программ, использующих эту реализацию. SOM не является объектно-ориентированным языком в полной мере, но соответствует таким принципам объектно-ориентированного программирования, как инкапсуляция (скрытое описание реализации объекта), наследование и полиморфизм.
В модели SOM классы представляют шаблоны дл объектов, определяющие их возможные свойства и поведение. Объекты - особые экземпляры классов. Однако, в отличие от классов в C++, классы SOM сами являются объектами, и в этом смысле они похожи на классы в "истинно" объектно-ориентированных языках - таких как Smalltalk. В то время как классы C++ - структуры этапа компиляции, которые исчезают во врем выполнения, классы SOM существуют в качестве классов-объектов на этапе выполнения. Поскольку все объекты SOM должны быть экземплярами классов SOM, необходима некая структура, экземплярами которой будут сами классы. Для этого SOM использует "метаклассы". (Метаклассы служат шаблонами для классов точно так же, как классы служат шаблонами для объектов.) Одно из преимуществ существования классов SOM в качестве классов-объектов заключается в том, что можно получать и обновлять информацию о классах динамически, во врем выполнения.
Модель SOM организует некий промежуточный слой между объектами и их клиентами, тем самым обеспечива свободный доступ к библиотекам классов. Классы SOM, или точнее, интерфейсы с ними, создаются с использованием основанного на спецификации COBRA языка определени интерфейсов (Interface Definition Language - IDL). IDL - это близкий к Cи, разработанный специально дл определения интерфейсов классов, независимых от языков. Применение IDL позволяет отделить интерфейс объекта от его реализации. При такой организации пользователь класса и разработчик его реализации вовсе не обязаны использовать один и тот же язык. После того как класс SOM определен, компилятор принимает IDL-текст и генерирует соответствующие привязки для текста реализации и заголовки для файлов клиента. (Уже существуют компиляторы DirectToSOM, которые минуют этап создания и компиляции IDL-текста, но конечный результат остается тем же.) В настоящий момент корпорация IBM поставляет привязки для классов, реализованных на C и C++, и со временем планирует выпустить их дл Smalltalk, OORexx и COBOL. Независимые фирмы также имеют подобные разработки. Для тех, кто хочет создать свои собственные привязки, IBM поставляет оболочку Emitter, входящую в пакет SOMObjects Developer Toolkit.
Здесь важно осознать, что при использовании SOM, объекты и их клиенты привязываются не друг к другу, а к интерфейсу. Это означает, что пока интерфейс с объектом остается неизменным, реализация его может изменяться, не затрагивая при этом клиентов объекта. Такой механизм преодолевает ограничения, присущие языкам со статической привязкой, таким как C++ или Object Pascal. В C++ классы и их клиенты жестко сцеплены (т. е. скомпилированный код клиента содержит константы, величины которых зависят от того, как организованы используемые ими классы). В результате вы не можете изменить классы без глобальной перекомпиляции при этом всех их клиентов. Для языков с динамическим связыванием - таких как Smalltalk или Objective C - это не представляет проблемы, однако для Cи++ может обернуться полным кошмаром. Данная ситуация означает, что, если вы измените один из базовых классов, добавив, к примеру, виртуальную функцию, вам придетс перекомпилировать не только клиентов того класса, который вы изменили, но и клиентов всех классов, порожденным данным (не в этом ли простая причина того, что C++ до сих пор не завоевал весь мир.) Поскольку модель SOM отделяет класс от его клиентов, она позволяет реализовать на C++ динамическую связь с объектами, как это делает Smalltalk.
Еще одно примечательное свойство SOM состоит в том, что она предусматривает наследование интерфейсов: подклассы SOM наследуют все методы, определенные в интерфейсах их родительских классов, даже если реализованы они на других языках.
Модель SOM также поддерживает множественное наследование (возможность производить подкласс из нескольких родительских классов). Одна из возникающих при этом проблем в том, что два или более родител могут использовать описания одного и того же метода, и, поскольку подкласс может унаследовать этот метод только от одного родителя, приходится искать способ разрешени конфликта. По умолчанию SOM использует левосторонний приоритет, заключающийся в том, что родитель, находящийся в иерархии слева, оказывается "главнее". Но если вам угодно использовать другое правило разрешения подобных ситуаций, вы можете создать новый метакласс и заменить механизм наследования, установленный SOM. Конечно, таким путем вы можете привести иерархию объектов в полный беспорядок, однако приятно знать, что в вашем распоряжении есть весьма гибкие средства.
За гибкость, предоставляемую SOM, приходится кое-чем расплачиваться. Дополнительный слой косвенных связей плюс использование метаклассов вызывают некоторое снижение производительности - в отдельных прикладных программах до 20%, - так что лучше обойтись без SOM в тех случаях, когда не нужна независимость от языка или когда вы часто обращаетесь к коротким методам. Однако Workplace Shell обычно обращается к длинным методам, что не приводит к значительным потерям в производительности.
Для того, чтобы работать с SOM эффективно, вам нужно познакомиться с иерархией классов SOM и с тем, какое место в ней занимает WPS. Эти взаимосвязи показаны ниже.
На вершине иерархии объектов SOM находится SOMObject - корень всех классов SOM. Все классы, в том числе и и классы WPS, прямым или косвенным образом наследуют свои свойства и поведение от SOMObject.
SOMObject
---------
|_____________________________________
| | |
SOMClass SOMClassMgr WPObject
-------- ----------- --------
__________________________________|______
| | |
_ WPAbstract _ WPFileSystem _ WPTransient
| ---------- | ------------ | -----------
|- WPClock |- WPFolder |- WPJob
|- WPCountry | WPDesktop |- WPPort
|- WPDisk | WPDrives |- WPMinWindow
|- WPKeyboard | WPStartUp |- WPQueueDriver
|- WPMouse | WPTemplates |- WPCnpView
|- WPPalette | WPMinWinViewer |- WPDiskCV
| WPColorPalette | WPFindFolder |- WPFolderCV
| WPFontPalette | WPNetGroup |- WPFilter
| WPSchemePalette | WPNetwork |- WPFinder
|- WPProgram | WPServer
|- WPShadow | WPShareDir
| WPNetLink |- WPDataFile
|- WPShredder WPBitmap
|- WPSound WPIcon
|- WPSpecialNeeds WPPointer
|- WPSpooler WPProgramFile
|- WPSystem WPCommandFile
|- WPPrinter WPMet
|- WPPower WPPif
|- WPTouch WPPrinterDriver
|- WPFntpnl
|- WPWinConfig
Корень всех классов SOM - SOMObject. Все классы прямым или косвенным образом наследуют свои свойства и поведение от SOMObject. Поскольку каждый класс представлен классом-объектом, а каждый класс-объект в свою очередь должен быть экземпляром метакласса (вспомните, что метаклассы являются шаблонами дл классов, а классы - шаблонами для объектов), то и класс SOMObject - экземпляр метакласса SOMClass.
Как мы уже отметили, и сами метаклассы предствляют собой объекты, поэтому дальше возникает вопрос: экземплярами чего являются метаклассы? Если строго следовать логике, ответом должен быть мета-метакласс, и так можно продолжать до бесконечности. Однако необходимо же с чего-то начать. И модель SOM определяет, что метаклассом всех метаклассов будет SOMClass (таким образом, SOMClass попадает в забавное положение, являясь экземпляром самого себя). SOMClass также является родительским классом для всех метаклассов. Все метаклассы порождаются от SOMClass. Неудивительно, если вы сейчас сбиты с толку. Главное, что нужно помнить, - это то, что методы, вызываемые из классов, берутся в SOMClass, а методы, вызываемые из объектов, - в SOMObject.
Другой важный подкласс SOMObject - SOMClassMgr. Этот класс ведет учет всех классов SOM, существующих в среде выполнения SOM, и помогает загружать и выгружать библиотеки классов. (Библиотеки классов SOM в это врем хранятся в виде DLL.)
SOMObject, SOMClass и SOMClassMgr, вместе с функциями инициализации и настройки среды выполнени SOM хранятся в SOM.DLL, который OS/2 загружает при своей инициализации. Когда запускается среда исполнения SOM, создается экземпляр класса SOMClassMgr, который продолжает существовать на всем протяжении работы OS/2. При первой ссылке на какой-либо класс объект SOMClassMgr загружает соответствующий DLL и создает экземпляр этого класса.
Продолжая спускаться по иерархии объектов SOM, мы войдем в область Workplace Shell, о чем станет ясно из префикса WP, присущего всем классам WPS. На вершине дерева WPS находится корень всех объектов WPS - WPSObject. Свойства, присущие всем объектам WPS, такие как название или пиктограмма, наследуются от WPSObject. Он порождает три основных класса - WPFileSystem, WPAbstract и WPTransient - в которых объекты WPS группируются по типу используемой ими памяти. Все объекты WPS попадают в один из этих трех классов.
Как заставить функции утилиты REXX работать с объектами SOM среды Workplace Shell.
В этой части обзора завершим рассмотрение иерархии классов WPS на базе модели SOM и расскажем о функциях библиотеки RexxUtil, предназначенной для совместной работы с WPS. Мы также перейдем к практическим применениям и начнем использовать объекты WPS в прикладных программах REXX.
Базовые классы WPS, WPFileSystem, WPAbstract и WPTransient, представляют собой классы памяти (storage classes), порожденные непосредственно из WPObject. Они названы классами памяти потому, что они отличаютс способами, с помощью которых объекты WPS хранят свои свойства и данные. Характеристики хранения остальных классов WPS наследуются от одного из этих трех классов. В части 1 показана иерархия WPS-классов, начиная с WPObject.
Объекты, образованные из WPFileSystem, представляют собой дисковые файлы и каталоги. Данные и свойства этих объектов хранятся в файлах и расширенных атрибутах этих файлов. (Расширенные атрибуты содержат дополнительную информацию о файле, которую использует OS/2.) Расширенные атрибуты, используемые средой WPS - это информация о классе (CLASSINFO), типе объекта (TYPE), длинном имени объекта (LONGNAME) и ассоциированной пиктограмме (ICON). Между прочим, не все файловые и операционные системы работают с расширенными атрибутами. Например, если вы скопируете файлы OS/2 на гибкий диск и затем видоизмените их в обычной среде MS-DOS (отличающейся от версии DOS, имеющейся в составе OS/2), то потеряете расширенные атрибуты, связанные с этими файлами.
Для объектов, образованных в классе WPAbstract, информация сохраняется в файлах OS2.INI и OS2SYS.INI. Они представляют устройства, такие, как принтер и мышь, либо внутренние объекты, такие как Shadow (команда быстрого вызова) и LaunchPad (Инструментальная панель). Эти объекты не связаны непосредственно с дисковыми файлами, но им необходимо иметь возможность постоянного запоминания информации, на тот случай, если у вас возникнет желание сохранять изменения, сделанные во время сеанса работы с устройством. Состояние каждого производного объекта класса WPAbstract хранится в файле INI внутри блока, идентифицируемого дескриптором данного объекта. (Дескриптор - handle - уникальный идентификатор, присваемый каждому объекту при его создании.) Поскольку объем хранящейся в INI-файлах информации достаточно велик, настоятельно рекомендуем иметь их резервные копии на случай, если эти файлы будут испорчены - такое иногда случается, особенно если был нарушен порядок выхода из системы.
Последний базовый класс WPS - WPTransient. Классы, производные от него, не имеют постоянных хранилищ данных. Они либо не располагают свойствами, которые необходимо сохранить, либо сами организуют их временное хранение. WPMinWindow, например, выводит на экран свернутую пиктограмму, отображающую выполняемую в данный момент программу. Так как при выходе из среды OS/2 работа программы будет прекращена, то нет нужды сохранять информацию о ней. Однако, экземпляр WPJob - это временно существующий объект, созданный объектом-принтером. Он записывает на диск временный файл, и нет смысла сохранять его после завершени вывода на печать.
Теперь, когда рассмотрены основы механизма наследования WPS, вы должны иметь представление о том, откуда объекты WPS "узнают" свои характеристики и поведение. Все классы WPS, обсуждавшиеся до сих пор, являются абстрактными: они существуют исключительно с целью обеспечить наследование и не реализованы как объекты. Вам не придется непосредственно использовать в своих прикладных программах ни один из этих классов. Однако прочие классы в иерархии WPS имеют вполне конкретное содержание, так давайте обсудим некоторые способы их использования в программах REXX.
REXX (REstructured eXtended eXecutor - реструктурированный расширенный исполнительный язык) - интерпретируемый язык, входящий в состав OS/2. Мы решили воспользоваться им, поскольку он прост дл освоения и имеется в распоряжении всех пользователей OS/2. Кроме того, REXX был создан как макроязык дл других прикладных программ и содержит ряд специальных служебных функций WPS.
Сервисные функции WPS не встроены в язык REXX, а хранятся в библиотеке RexxUtil. Чтобы воспользоватьс ими, следует зарегистрировать функции RexxUtil в процессоре REXX. Вы можете зарегистрировать либо только те функции, которые вам нужны, либо всю библиотеку целиком. Если объем имеющейся в вашем распоряжении памяти ограничен, то вы можете загрузить лишь необходимые вам функции, так как функции WPS составляют лишь части библиотеки RexxUtil. В табл. 1 перечислены все функции WPS, имеющиеся в RexxUtil (список есть и в оперативной документации по языку REXX OS/2). После того, как функции RexxUtil будут загружены, их можно использовать во всех сеансах OS/2 до тех пор, пока вы не выгрузите их или не отключите систему.
Сервисные функции WPS, предоставляемые внешней библиотекой RexxUtil. Вы можете зарегистрировать либо необходимые функции, либо всю библиотеку.
Имя функции | Описание | Синтаксис |
---|---|---|
SysCopyObject | Копирует существующий WPS-объект в новое местоположение | rc=SysCopyObject(nameofObject,nameofDest) |
SysCreateObject | Создает новый экземпляр WPS-класса | rc=SysCreateObject(classname,title,location<,setup><,option>) |
SysCreateShadow | Создает команду быстрого вызова существующего WPS-объекта | rc=SysCreateShadow(nameofObject,nameofDest) |
SysDeregisterObjectClass | Удаляет определение WPS-класса из реестра | rc=SysDeregisterObjectClass(classname) |
SysDestroyObject | Уничтожает WPS-объект | rc=SysDestroyObject(nameofObject) |
SysMoveObject | Перемещает существующий WPS-объект в новое место | SysMoveObject(nameofObject,nameofDest) |
SysOpenObject | Открывает существующий WPS-объект | rc=SysOpenObject(nameofObject,View,Flag) |
SysQueryClassList | Получает список зарегистрированных WPS-классов | SysQueryClassList stemVariable |
SysRegisterObjectClass | Помещает определение WPS-класса в реестр | rc=SysRegisterObjectClass(classname,DLLname) |
SysSaveObject | Записывает файл OS2.INI на диск | rc=SysSaveObject(nameofObject,fAsync) |
SysSetObjectData | Устанавливает значения величин в объекте WPS | SysSetObjectData(nameofObject,setupString) |
Программа REXX, регистрирующая всю библиотеку RexxUtil, приведена в лист. 1. На лист. 2 представлена программа REXX, которая регистрирует лишь индивидуальные функции WPS. Если вы не знакомы с языком REXX, но хотели бы поэкспериментировать с ним, просто введите текст программы в обычный текстовый файл и присвойте имени файла расширение CMD. Затем попытайтесь запустить его из командной строки OS/2.
Лист. 1. Программа для регистрации всех функций RexxUtil.
/* Зарегистрировать и загрузить все функции библиотеки RexxUtil */
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
call SysLoadFuncs;
Лист. 2. Программа для регистрации всех индивидуальных функций.
/* Зарегистрировать и загрузить избранные функции библиотеки RexxUtil */
call RxFuncAdd 'SysOpenObject', 'RexxUtil', 'SysOpenObject';
call RxFuncAdd 'SysCopyObject', 'RexxUtil', 'SysCopyObject';
call RxFuncAdd 'SysMoveObject', 'RexxUtil', 'SysMoveObject';
Если вы получите сообщение об ошибках, то убедитесь в том, что REXX был инсталлирован, и что маршрут доступа к библиотеке указывает на библиотеки REXX - REXX.DLL, REXXAPI.DLL, REXXINIT.DLL и REXXUTIL.DLL. Кроме того, убедитесь, что в первой строке вы разместили комментарий. Все программы REXX должны начинаться с комментария, чтобы отличить их от командных файлов, которые также имеют расширение .CMD. Если файл начинается не с комментария, то OS/2 рассматривает его как командный файл и направляет в командный процессор, а не в интерпретатор REXX. Все остальные комментарии, за исключением первой строки, игнорируются. Если у вас все еще есть неясности, то сверьтесь с оперативной документацией REXX в папке Information.
Теперь, когда вы знаете, как загрузить функции RexxUtil, которые мы будем использовать в наших примерах, давайте подробнее ознакомимся с некоторыми их них. Удобно начать с SysQueryClassList. В части 1 отмечалось, что экземпляр SOMClassMgr создается при инициализации операционной среды SOM. Он отвечает за загрузку и за создание объектов, принадлежащих классам, а также за ведение реестра всех классов SOM, существующих в данной среде. SysQueryClassList запрашивает у объекта SOMClassMgr список зарегистрированных классов. В листинге программы 3 показано, как получить список и вывести его на экран. В списке приведены как имя класса, так и имя содержащей его DLL.
Лист.3. Программа для вывода на дисплей зарегистрированных классов SOM.
/* Запросить доступные классы и вывести их на экран */
/* Зарегистрировать функции RexxUtil */
call RxFuncAdd 'SysQueryClassList', 'RexxUtil', 'SysQueryClassList';
/* Получить доступные классы и поместить их в массив */
call SysQueryClassList 'classList.';
/* Прочитать каждый класс в списке и вывести на дисплей */
do i = 1 to classList.0
say classList.i;
end
Если нужный вам класс отсутствует в полученном списке, то вы можете загрузить его с помощью функции SysRegisterObjectClass библиотеки RexxUtil. Синтаксис этой функции таков:
result=SysRegisterObjectClass('NewClass', 'NewClassDLL')
Замените NewClass и NewClassDLL соответственно именем класса, который вы хотите загрузить и именем файла DLL, в которой он находится. Функция передает в вызывающую программу 1 ("Истина"), если класс был успешно зарегистрирован, и 0 ("Ложь") в противном случае. Создание нового класса SOM выходит за рамки данной статьи, но если вы создадите свой собственный класс SOM, то загружать его в Workplace Shell будете именно таким способом.
После того, как вы удостоверитесь, что нужный вам класс доступен, можно использовать его для создани новых объектов. Функция SysCreateObject библиотеки RexxUtil может создавать новые объекты для замены или обновления существующих объектов. Синтаксис таков:
result=SysCreateObject ('Classname', 'Title', 'Location', 'Setup', 'Option')
Classname должен быть классом, который в данный момент зарегистрирован в WPS. Примеры часто используемых классов - WPProgram, WPFolder и WPDataFile. Title - длинное имя, которое появляется под пиктограммой объекта на "рабочем столе".
Location - папка, в которую будет помещен объект. Этот параметр может быть задан как путь доступа файловой системы или как идентификатор объекта папки. Идентификаторы объектов уникальны для каждого объекта и имеют синтаксис <objectname>, где уникальное им объекта заключено в угловые скобки. Идентификаторы объектов, присвоенные по умолчанию, назначаются всем стандартным объектам WPS, и большинство из них начинается с символов "<WP_>". Во избежание проблем вам не следует давать новым объектам имена, принятые по умолчанию, и для верности никогда не начинайте имя с "WP".
Setup - строка необязательных параметров для задани значений переменных, которые изменяются от класса к классу. Один из параметров начальной установки, общий для всех классов - это идентификатор объекта. Можно и не назначать объекту идентификатор в момент его создания, но и невозможно программно управлять объектом, не имеющим идентификатора. Об управляющих последовательностях начальной установки мы поговорим в нашей следующей статье, а пока достаточно упомянуть, что их использование не является обязательным. Все значения этих последовательностей, заданных по умолчанию определяются классом новых объектов.
Options - код, указывающий OS/2, что делать, если объект, который вы хотите создать, уже существует. Возможны три варианта:
В листинге программы 4 показано, как создать новый программный объект для редактора OS/2 Editor и поместить его на "рабочий стол".
Лист. 4. Программа для создания нового объекта OS/2 Editor.
/* создать на "рабочем столе" программный объект и вывести на
экран результаты */
/* загрузить функцию RexxUtil */
call RxFuncAdd 'SysCreateObject', 'RexxUtil', 'SysCreateObject';
setupString = 'OBJECTID=<RexxTestProgram>;' || 'EXENAME=\OS2\E.EXE';
rc = SysCreateObject('WPProgram', 'Rexx Test Program',,
',<WP_DESKTOP>', setupString );
if rc = 1 then
say 'Program object created w/Rexx'
else say 'Could not create Program w/Rexx'
Создайте специализированные объекты SOM для своего "рабочего стола".
В третьей части обзора мы более подробно рассмотриваем различные управляющие последовательности начальной установки REXX, которые вы можете использовать для настройки своего "рабочего стола".
Если вы исследовали OS/2 Workplace Shell, то, возможно, знаете о неисчислимых параметрах настройки, предусмотренных в Блокноте установки (Settings Notebook) WPS-объектов. Каждый из этих параметров в свою очередь может быть сконфигурирован с помощью управляющих последовательностей начальной установки функций SysCreateObject и SysSetObjectData библиотеки RexxUtil. Таким образом, в дополнение к конфигурирированию объектов через "Блокнот установки" или с помощью техники drag-and-drop вы можете использовать для их настройки REXX. Во многих случаях оказывается быстрее воспользоваться методом непосредственных манипуляций вместо того, чтобы написать REXX-программы, но функции REXX незаменимы, когда вам требуется провести настройку большого числа рабочих станций. Настройка "рабочего стола" с помощью REXX также представляет собой эффективный способ обеспечения безопасности, так как вы можете восстановить утерянные или испорченные объекты, просто заново выполнив REXX-программу.
Предположим, что вы - сетевой администратор и вам нужно создать специализированные "Инструментальные панели" для каждого пользователя. Каждый подразделение хочет, чтобы наиболее часто используемые программы находились на линейке, отделенной от стандартной "Инструментальной панели" Launchpad, - плановый отдел, например, пользуется в основном инструментами дл планирования деятельности предприятия, а отдел маркетинга чаще использует электронные таблицы и текстовые процессоры.
К сожалению, OS/2 не имеет шаблона дл "Инструментальных панелей"; если вы хотите создать новую "Инструментальную панель" с помощью "Блокнота установки", вам нужно сделать копию стандартной "Инструментальной панели" и удалить все ее объекты (перетащить их в мусорную корзину или выбрать пункт Delete (удалить) из всплывающего меню объекта). Затем вы должны заполнить "Инструментальную панель", перетаскивая на нее новые программные объекты. Поскольку параметры "Инструментальной панели" не сохраняются в отдельном файле на диске (класс WPLaunchPad - потомок класса WPAbstract), вы не можете скопировать их на дискету для последующего распространения. Следовательно, вы должны повторять процедуру заново для каждого "рабочего стола". Создание специальной "Инструментальной панели" поначалу кажетс простым, но к моменту, когда вы закончите ее установку на десятой рабочей станции, у вас, возможно, появитс желание сменить место работы.
Однако эту же задачу можно решить с использованием REXX. Во-первых, вам надо выяснить, какую прикладную программу хочет загрузить каждый отдел. Допустим, плановый отдел хочет поместить на новую "Инструментальную панель" несколько настольных инструментов OS/2: "Калькулятор", "Календарь", "Ежедневник" и "Ежемесячник", "Часы" и "Список неотложных дел". Отдел высказал пожелание, чтобы "Ежемесячник" был помещен в выдвижной ящик, расположенный над "Ежедневником", а "Часы" - над "Списком неотложных дел".
Чтобы получить доступ к каждому из этих объектов в
среде REXX, вам нужно знать их идентификаторы или их
маршрута доступа и имена файлов - если таковые имеются.
Идентификаторы объектов предпочтительны, так как
объекты могут быть перемещены. Идентификаторы объектов
уникальны для каждого объекта и заключаются в угловые
скобки:
<objectname>
Всем стандартным объектам WPS назначаетс
идентификаторы по умолчанию, и большинство из них
начинаются с одних и тех же трех символов: WP_. Таким
образом, вам следует избегать назначения объектам
идентификаторов, начинающихся с этих трех символов.
Врезка "Используемые по умолчанию объекты Workplace Shell" показывает применяемые по умолчанию идентификаторы для большинства WPS-объектов, используемых в OS/2 Warp. Мы более подробно объясним механизм ссылок на идентификаторы ниже, а сейчас приведем идентификаторы, нужные для нашего примера:
Имя объекта | Идентификатор объекта | Класс объекта | Местонахождение |
---|---|---|---|
16-цветная палитра | <WP_LORESCLRPAL> | WPColorPalette | <WP_CONFIG> |
256-цветная палитра | <WP_HIRESCLRPAL> | WPColorPalette | <WP_CONFIG> |
Сведения о прикладных программах | <WP_APPLBK> | WPProgram | <WP_INFO> |
Калькулятор | <WP_DCALC> | WPProgram | <WP_TOOLS> |
Календарь | <WP_DCALEM> | WPProgram | <WP_TOOLS> |
CD-плейер | <MMPM_CDPLAYER1> | WPProgram | <MMPM2_FOLDER> |
Программа просмотра буфера обмена | <WP_CLIPV> | WPProgram | <WP_TOOLS> |
Приглашения на ввод команды | <WP_PROMPTS> | WPFolder | <WP_DESKTOP> |
Командная ссылка | <WP_CMDREF> | WPProgram | <WP_INFO> |
Страна | <WP_CNTRY> | WPCountry | <WP_CONFIG> |
Ежедневник | <WP_DIARY> | WPProgram | <WP_TOOLS> |
"Рабочий стол" | <WP_DESKTOP> | WPDesktop | <WP_DESKTOP> |
Инсталляция драйвера устройства | <WP_DDINST> | WPProgram | <WP_CONFIG> |
Цифровой аудиоплейер | <MMPM_DAPLAYER1> | WPProgram | <MMPM2_FOLDER> |
DOS с накопителя A: | <WP_DOS_DRV_A> | WPProgram | <WP_PROMPTS> |
Полный экран DOS | <WP_DOSFS> | WPProgram | <WP_PROMPTS> |
Окно DOS | <WP_DOSWIN> | WPProgram | <WP_PROMPTS> |
Накопители | <WP_DRIVES> | WPDrives | <WP_DESKTOP> |
Двойная загрузка | <WP_DBOOT> | WPProgram | <WP_PROMPTS> |
Расширенный редактор | <WP_EPM> | WPProgram | <WP_TOOLS> |
Палитра шрифтов | <WP_FNTFAL> | WPFontPalette | <WP_CONFIG> |
Игры | <WP_GAMES> | WPFolder | <WP_DESKTOP> |
Глоссарий | <WP_GLOSS> | Mindex | <WP_INFO> |
Редактор пиктограмм | <WP_ICON> | WPProgram | <WP_TOOLS> |
Информация | <WP_INFO> | WPFolder | <WP_DESKTOP> |
Клавиатура | <WP_KEYB> | WPKeyboard | <WP_CONFIG> |
Инструментальная панель | <WP_LAUNCHPAD> | WPLaunchpad | <WP_DESKTOP> |
Игра Mah-jongg | <MAH_EXE> | WPProgram | <MAH_FOLDER> |
Mah-jongg солитер | <MAH_FOLDER> | WPFolder | <WP_GAMES> |
Служебный "рабочий стол" | "WP_MAINT> | WPDesktop | <WP_DESKTOP> |
Главный индекс подсказки | <WP_MINDEX> | Mindex | <WP_INFO> |
Музыкальный MIDI-плейер | <MMPM_MIDIPLAYER1> | WPProgram | <MMPM2_FOLDER> |
Переносимые прикладные программы | <WP_MIGAPP> | WPProgram | <WP_CONFIG> |
Программа просмотра минимизированных окон | <WP_VIEWER> | WPMinWinViewer | <WP_DESKTOP> |
MM-конвертер данных | <MMPM2_MMCONVERTER> | WPProgram | <MMPM2_FOLDER> |
Ежемесячник | <WP_DMNTH> | WPProgram | <WP_TOOLS> |
Мышь | <WP_MOUSE> | WPMouse | <WP_CONFIG> |
Папка мультимедиа | <MMPM2_FOLDER> | WPFolder | <WP_DESKTOP> |
Информация мультимедиа | <WP_MULTIMBK> | WPProgram | <WP_INFO> |
Установка мультимедиа | <MMPM2_SETUP> | WPProgram | <MMPM2_FOLDER> |
Сеть | <WP_NETWORK> | WPNetwork | <WP_DESKTOP> |
Нигде | <WP_NOWHERE> | WPFolder | <WP_DESKTOP> |
Шахматы OS/2 | <WP_CHESS> | WPProgram | <WP_GAMES> |
Полный экран OS2 | <WP_OS2FS> | WPProgram | <WP_PROMPTS> |
Система OS/2 | <WP_OS2SYS> | WPFolder | <WP_DESKTOP> |
Системный редактор OS/2 | <WP_SYSED> | WPProgram | <WP_TOOLS> |
Окно OS/2 | <WP_OS2WIN> | WPProgram | <WP_PROMPTS> |
PCMCIA Plug and Play | <WP_CMPNP> | WPCmpnp | <WP_CONFIG> |
Сведения о производительности | <WP_PERFBK> | WPProgram | <WP_INFO> |
Программа просмотра изображений | <WP_PICV> | WPProgram | <WP_TOOLS> |
Карта PM | <WP_CHART> | WPProgram | <WP_TOOLS> |
Управление энергопотреблением | <WP_OWER> | WPPower | <WP_CONFIG> |
Принтер | <WP_PDVIEW> | PDView | <WP_DESKTOP> |
Информация о печати | <WP_PRINTBK> | WPProgram | <WP_INFO> |
Производительность | <WP_TOOLS> | WPFolder | <WP_DESKTOP> |
Синхронизация | <WP_PULSE> | WPProgram | <WP_TOOLS> |
ReadMe | <WP_RDME> | WPShadow | <WP_INFO> |
Информация REXX | <WP_REXREF> | WPProgram | <WP_INFO> |
Схемная палитра | <WP_SCHPAL28> | WPSchemePalette | <WP_CONFIG> |
Поиск и сканирование файлов | <WP_SEEK> | WPProgram | <WP_TOOLS> |
Селективная инсталляция | <WP_INST> | WPProgram | <WP_CONFIG> |
Мусорная корзина | <WP_SHRED> | WPShredder | <WP_DESKTOP> |
Солитер-Клондайк | <WP_KLDK> | WPProgram | <WP_GAMES> |
Звук | <WP_SOUND> | WPSound | <WP_CONFIG> |
Спулер | <WP_SPOOL> | WPSpool | <WP_CONFIG> |
Электронные таблицы | <WP_SPREAD> | WPProgram | <WP_TOOLS> |
Начальный запуск | <WP_START> | WPStartup | <WP_DESKTOP> |
Система | <WP_SYSTEM> | WPSystem | <WP_CONFIG> |
Системные часы | <WP_CLOCK> | WPClock | <WP_CONFIG> |
Установка системы | <WP_CONFIG> | WPFolder | <WP_DESKTOP> |
Шаблоны | <WP_TEMPS> | WPTemplates | <WP_DESKTOP> |
Список неотложных дел | <WP_TODO> | WPProgram | <WP_TOOLS> |
Прикосновение | <WP_TOUCH> | WPTouch | <WP_CONFIG> |
Сведения о торговой марке | <WP_TRADEMBK> | WPProgram | <WP_INFO> |
Учебник | <WP_TUTOR> | WPProgram | <WP_INFO> |
Деинсталляция | <WP_UNINST> | WPProgram | <WP_CONFIG> |
Видеоплейер | <MMPM2_SOFTWARE_MOTION_VIDEO1> | WPProgram | <MMPM2_FOLDER> |
Регулятор громкости | <MMPM2_MASTERVOLUME_D> | WPProgram | <MMPM2_FOLDER> |
Полный экран WIN-OS2 | <WP_WINFS> | WPProgram | <WP_PROMPTS> |
Окно WIN-OS2 | <WP_WIN2WIN> | WPProgram | <WP_PROMPTS> |
Начальная установка WIN-OS2 | <WP_WINCFG> | WPWinConfig | <WP_CONFIG> |
Windows в OS/2 | <WP_WINOS2BK> | WPProgram | <WP_INFO> |
Теперь, когда мы располагаем нужными идентификаторами объектов, мы можем создать новую "Инструментальную панель" с помощью функции SysCreateObject библиотеки RexxUtil, которая позволяет создавать новые объекты и конфигурировать их. Она принимает пять параметров, в том числе несущие информацию о классе (Class), имени (Title) и местонахождении (Location) объекта, а также необязательные параметры Setup String (управляюща последовательность начальной установки) и Option Code (Код варианта). В случае если нужный вам объект уже существует, "Код варианта" обеспечивает выбор одного из вариантов: завершить выполнение функции неудачей (F) - это действие предпринимается по умолчанию, если вы не укажете конкретный Option Code; заменить существующий объект (R); или изменить существующий объект (U). В варианте изменения объект приобретает новые свойства, предоставленные управляющей последовательностью начальной установки.
Управляющая последовательность начальной установки - набор комбинаций "ключевое слово=значение", разделенных точками с запятой: EXENAME=C:\MDOS\BASIC.COM; STARTUPDIR=C:\MDOS; PROGTYPE=VDM; Ключевые слова представляют свойства объекта, которые меняются в зависимости от класса объекта и его места в иерархии WPS.
Существуют ключевые слова и необязательные параметры, позволяющие управлять любой характеристикой, которую вы можете задать из Блокнота установки и даже некоторыми недоступными оттуда. Они предлагают широкий набор функций, начиная от используемых для определени идентификатора объекта, и кончая такими, которые назначают тип сеанса и накладывают ограничения на возможность просмотра и удаления объекта.
Значительное число доступных параметров установки само по себе может привести в замешательство новичка, что, вероятно, и служит причиной того, что обща документация по языку REXX содержит лишь несколько примеров. Они слишком длинны, чтобы привести их здесь, но мы поместили в оперативную информационную службу PC Magazine Online файл, содержащий большинство параметров начальной установки, которые, по нашему мнению, могут пригодиться системному администратору. Они сгруппированы в таблицы по классам, начиная с WPObject. Поскольку свойства и поведение наследуются, установки WPObject передаются всем его подклассам. Для подклассов мы показываем только те установки, которые замещают или расширяют установки родительского класса. Иерархи классов WPS приведена в частях 1 и 2 нашей серии статей о SOM.
На лист. 5 показана программа REXX, служащая дл создания новой Инструментальной панели и размещения на ней перечисленных ранее прикладных программ. Заметьте, что мы назначаем переменную для управляющей последовательности начальной установки и связываем комбинации "ключевое слово=значение" с помощью символа ||. Это сделано главным образом для удобства чтения; вы можете вводить управляющую последовательность буквально такой, как она есть. Обратите также внимание на запятые, расставленные в конце некоторых строк. В языке REXX запятая в конце строки означает, что текст программы продолжается на следующей строке. Если вы разобьете программу на строки иначе, нежели в нашем примере, проверьте, что вы правильно рассставили запятые.
Лист.5. В этой части программы REXX делается попытка создания новой "Инструментальной панели" и показано, что из этого получилось
/* Создание новой "Инструментальной панели" на рабочем
столе и вывод результатов на экран */
/* загрузка функции RexxUtil */
call RXFuncAdd 'SysCreateObject', 'RexxUtil', 'SysCreateObject';
setupString = ,
'OBJECTID=<OpsLaunchPad>;' ||,
'FPOBJECTS=<WP_DCALC>,<WP_DCALEM>,<WP_DDIARY>,<WP_TODO>;' ||,
'DRAWEROBJECTS=3,<WP_DMNTH,>;'
rc = SysCreateObject('WPLaunchPad', 'Operations LaunchPad',,
'<WP_DESKTOP>', setupString );
if rc = 1 then
say 'Launchpad object created w/Rexx'
else say 'Could not create Launchpad w/Rexx'
Ключевое слово FPOBJECTS добавляет новые объекты в
правый конец горизонтально сконфигурированной палитры
или на самый верх размещенной по вертикали палитры. В
техническом отношении эта программа добавляет к
"Инструментальной панели" команды быстрого вызова
объектов, а не подлинные объекты. Но вам не нужно явно
создавать команду быстрого вызова, так как
"Инструментальная панель" делает это за вас. Синтаксис
таков:
FPOBJECTS=objectID1, objectID2, objectID3...;
Обратите внимание, что вы должны использовать
запятые для разделения идентификаторов объектов и точку
с запятой в конце управляющей последовательности
начальной установки. Многоточие (...) указывает, что
последовательность может продолжаться неопределенно
долго. В нашем случае мы расширяем палитру слева
направо: команда быстрого вызова "Калькулятора",
"Календаря", "Ежедневника" и "Списка неотложных дел".
(По умолчанию принимаются горизонтальные
"Инструментальные панели".)
Посредством DRAWEROBJECTS добавляются объекты в
выдвижной ящик над одним из элементов палитры.
Выдвижной ящик изображается маленькой полоской; если в
ящике содержатся какие-либо объекты, в середине полоски
появляется метка. Принят следующий синтаксис:
DRAWEROBJECTS=drawer_number, objectID1, objectID2...;
Выдвижные ящики идентифицируются по номерам и
располагаются последовательно слева направо (или снизу
вверх в вертикальной "Инструментальной панели"). В
нашем примере палитра содержит четыре объекта, и
"Ежедневник" находится в позиции 3. Так как мы хотели
поместить "Ежемесячник" выше "Ежедневника", он попадает
в выдвижной ящик 3. Обратите внимание, что запята
отделяет номер ящика от идентификаторов объектов и
идентификаторы объектов друг от друга. Вы можете
поместить в ящик более одного объекта, но из-за
особенностей синтаксиса конфигурировать можно лишь один
выдвижной ящик за один раз.
Следовательно, лист. 5 не имеет элемента, который помещал бы "Часы" в ящик, находящийся над "Списком неотложных дел". Чтобы поместить объекты в дополнительные ящики, вам следует воспользоватьс функцией SysSetObjectData, изменив вновь созданные "Инструментальные панели".
SysSetObjectData позволяет вам изменять параметры
существующих объектов. Использовать ее намного проще,
чем SysCreateObject, которая, будучи применена с
параметром модификации (U) может служить для тех же
целей. Синтаксис функции SysSetObjectData следующий:
result=SysSetObjectData('NameofObject', 'Setup')
Переменная result представляет собой return-код.
Функция передает в вызывающую программу 1, если она
завершилась успешно, и 0 в случае неудачи. Если вы,
например, попытаетесь модифицировать объект, которого
не существует на "рабочем столе", то функция завершитс
неудачей. NameofObject может быть либо идентификатором
объекта, либо, в случае потомков класса WPFileSysytem,
представлять собой путь доступа файловой системы к
объекту, который вы хотите изменить. (Помните, что
объекты, порожденные классом WPFileSysytem
соответствуют каталогам и файлам. Любой другой тип
объекта нуждается в идентификаторе объекта.) Setup -
управляющая последовательность начальной установки, в
которой используется тот же самый формат, что и в
управляющей последовательности, применяемой функцией
SysCreateObject.
Для настройки "рабочего стола" нам нужно еще добавить "Часы" в выдвижной ящик, расположенный выше "Списка неотложных дел" и, кроме того, внести некоторые другие изменения. Создав операционную "Инструментальную панель", мы обнаруживаем, что пиктограммы объектов почти неразличимы, и пользователи могут предпочесть иметь перед глазами описание каждого элемента, вместо одной лишь пиктограммы. На лист. 6 показано, как добиться этого с помощью функции SysSetObjectData. Обратите внимание, что свойствам LPTEXT и LPDRAWERTEXT присвоено значение YES (ДА), чтобы выводить под пиктограммами имена объектов. LPTEXT используется дл объектов палитры, а LPDRAWERTEXT - для объектов выдвижных ящиков.
Лист. 6. С помощью SysObjectData можно дополнить пиктограммы объектов описаниями каждого из элементов.
/* Внесение изменений в "Инструментальную панель" и
вывод результатов на экран */
/* Загрузка функции RexxUtil */
call RXFuncAdd 'SysObjectData', 'RexxUtil', 'SysObjectData';
setupString = ,
'DRAWEROBJECTS=4,<WP_CLOCK>;' ||,
'LPTEXT=YES;' ||,
'LPDRAWERTEXT=YES;'
rc = SysObjectData('<OpsLaunchPad>', setupString );
if rc = 1 then
say 'Successfully added objects to LaunchPad'
else say 'Could not added objects to LaunchPad'
И наконец, отдел маркетинга хочет поместить на свои "Инструментальные панели" Microsoft Word и Excel, вместе с некоторыми другими, менее известными пакетами. До сих пор во всех наших примерах мы либо назначали идентификаторы новым объектам, либо использовали идентификаторы по умолчанию для объектов, поставляемых вместе с OS/2; мы не работали с прикладными программами, которые добавлялись позднее. Существует несколько способов, позволяющих определить, каким идентификатором объекта следует воспользоваться.
Во-первых, для прикладной программы можно создать программный ссылочный объект и назначить ему идентификатор объекта. Создать программный ссылочный объект - то же самое, что перетащить шаблон Program на "рабочий стол" и сконфигурировать его. Вам нужно по меньшей мере знать местоположение EXE-файла программы. Возможно, вы также захотите знать, принимает ли он какие-либо параметры и каков его рабочий каталог. Эти необязательные величины устанавливаются с помощью ключевых слов EXENAME, PARAMETERS и STARTUPDIR соответственно.
На лист. 7 показан процесс создания программной ссылки для системного редактора System Editor OS/2. Мы расположили новый программный объект в папке "рабочего стола", но вы можете поместить его в любую папку по вашему выбору. Эта программа уже имеет ссылочный объект, но вы можете не знать его принимаемого по умолчанию идентификатора. Основным моментом при этом является то, что при создании новой программной ссылки надо назначить ей идентификатор объекта, чтобы знать, как обратиться к нему, когда он будет использоваться в других функциях.
Лист. 7. Если вам не известен идентификатор объекта прикладной программы, вы можете создать новую программную ссылку и назначить новый идентификатор.
/* Создание программного объекта на рабочем столе и
вывод результатов на экран */
/* Загрузка функции RexxUtil */
call RXFuncAdd 'SysCreateObject', 'RexxUtil', 'SysCreateObject';
setupString = ,
'OBJECTID=<MyEditor>;' ||,
'EXENAME=\OS2\E.EXE';
rc = SysCreateObject('WPProgram', 'System Editor',,
'<WP_DESKTOP>', setupString );
if rc = 1 then
say 'Program object created w/Rexx'
else say 'Could not createProgram w/Rexx'
Образец программы, показанный на лист. 8, выводит на экран список активных идентификаторов объектов. Поскольку список будет длинным, вы, возможно, пожелаете сохранить результат в файле. В случае если вы не укажете идентификатор объекта, WPS назначает его самостоятельно, и некоторые из этих идентификаторов могут выглядеть весьма загадочно. Просматривая список, составленный нашей программой, мы обнаружили, что <WP_CWINWORDWINWORD> и <WP_CEXCELEXCELTAMICROSOF> - вероятные кандидаты для Microsoft Word и Excel. Попробовав их в подпрограмме REXX, мы обнаружили, что наши предположения были правильными.
Лист. 8. С помощью этой короткой REXX-программы вы можете вывести на экран список активных идентификаторов объектов.
/* Вывод на экран идентификатора объекта, известного
оболочке WPS */
call RXFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs';
call sysloadfuncs
result = SysIni( 'USER', 'PM_Workplace:Location', 'ALL:' 'ids')
if result \= 'ERROR:' then
do i = 1 to ids.0
say ids.i
end
Мы надеемся, что этот цикл статей поможет вам составить представление о мощи и гибкости среды Workplace Shell, и побудит вас приступить к самостоятельному исследованию мира системной модели объектов SOM.
Габриель Ганьон - менеджер в области информационных технологий (г. Бостон).