|
|||||||||||||||||||||||||||||||||||||||||||||
|
Глава 10 Разработка СОМ-объектов с помощью языков сценариев Во всех сценариях WSH, которые мы рассматривали ранее, создавались экземпляры внешних СОМ-объектов, являющихся серверами автоматизации, после чего мы не задумываясь использовали свойства и методы этих объектов. В основном СОМ-объекты создаются в виде откомпилированных модулей с помощью универсальных языков типа Visual С++ или Visual Basic, однако с помощью специальной технологии Windows Script Components можно зарегистрировать в системе СОМ-объект, написанный на языке JScript или VBScript, причем для этого не нужно проводить никакой компиляции исходного кода сценария! Таким образом, любой сценарий WSH можно "упаковать" в СОМ-объект (мы будем называть такие объекты компонентами-сценариями или объектами-сценариями) и использовать его в приложениях, написанных на любом языке, который позволяет подключать внешние объекты. Преимуществами компонентов-сценариев над обычными откомпилированными компонентами (как и вообще любой интерпретируемой программы над компилируемой) является простота разработки, внесения изменений и распространения объектов-сценариев, недостатками — более медленная скорость работы и возможность внесения несанкционированных изменений в исходный код компонентов. В этой главе мы кратко опишем механизм работы объектов-сценариев и внутреннюю структуру файлов с описанием таких объектов. Также будет подробно разобран пример создания, регистрации и использования объекта-сценария, предназначенного для создания архивных копий файлов. Технология Windows Script Components Сразу оговоримся, что мы будем рассматривать только объекты-сценарии, которые являются серверами автоматизации (т.е. предоставляют свои свойства и методы другим приложениям), не затрагивая вопросы разработки специальных объектов для использования внутри HTML- или ASP-страниц (Active Server Pages). Механизм работы объектов-сценариев базируется на технологии ActiveX Scripting, основную роль здесь играет динамическая библиотека Scrobj.dll, которая является оболочкой компонентов-сценариев и отвечает за функционирование файла-сценария в качестве СОМ-объекта. С точки зрения технологии СОМ эта библиотека для объектов-сценариев действует как внутренний сервер (inprocess server). Другими словами, оболочка компонентов-сценариев Scrobj.dll отвечает за то, чтобы при вызове из внешнего приложения метода объекта-сценария или обращении к его свойству запускалась соответствующая функция, описанная в этом сценарии. Для этого на уровне операционной системы незаметно для самого объекта-сценария и для приложения, в котором создается экземпляр этого объекта, производятся следующие действия. ? При регистрации объекта-сценария в разделе HKEY_CLASSES_ROOT\CLSIDсистемного реестра создается новый подраздел, название которого совпадает с глобальным кодом (CLSID) регистрируемого объекта. В этом новом разделе создается подраздел InprocServer32, значением по умолчанию которого является полный путь к библиотеке Scrobj.dll. Кроме InprocServer32, создаются подразделы ProgID(программный идентификатор объекта) и ScripletURL(полный путь к файлу объекта-сценария). ? Если создание экземпляра объекта из внешнего приложения происходит с помощью программного идентификатора (ProgID) объекта, то сначала определяется глобальный код (CLSID) этого объекта. Для этого в разделе реестра HKEY_LOCAL_MACHINE\SOFTWARE\Classesищется подраздел с именем, которое совпадает с программным идентификатором объекта (этот подраздел создается при регистрации объекта-сценария), и в качестве глобального кода берется значение параметра CLSIDиз этого подраздела. ? По известному глобальному коду объекта происходит поиск раздела с нужным названием в HKEY_CLASSES_ROOT\CLSID, после чего определяется значение подраздела InprocServer32(путь к библиотеке Scrobj.dll) и загружается оболочка компонентов-сценариев Scrobj.dll. ? Библиотека Scrobj.dll загружает указанный в подразделе ScripletURLфайл со сценарием и перенаправляет вызовы методов объекта в этот сценарий. Таким образом, нам остается лишь научиться правильным образом создавать файлы с исходным кодом компонентов-сценариев и регистрировать эти файлы в системе в качестве СОМ-объектов. Компоненты-сценарии, реализованные в технологии Windows Script Components, представляют из себя файлы с расширениями wsc (WSC-файлы), которые содержат специальную XML-разметку (объектная модель WSC XML), к описанию которой мы и перейдем. Схема WSC XML Ранее в главе 3 отмечалось, что объектная модель, которая используется при создании многозадачных сценариев (WS-файлов), была в основном позаимствована из схемы WSC XML, поэтому многие элементы WSC-файлов окажутся вам знакомыми. В листинге 10.1 приводится несколько упрощенная (некоторые необязательные атрибуты у XML-элементов опущены) схема, поясняющая иерархию и порядок появления элементов в WSC-файле. Листинг 10.1. Упрощенная схема WSC XML<?xml version="1.0" encoding="windows-1251"?> <package> <component [id="ComponentID"]> <registration progid="ProgID" class id="GUID" [description="Description"] [version="Version"]> <script> Сценарии подключения и отключения </script> </registration> <public> <property name="PropertyName"> <get [internalName="getFunctionName"]/> <put [internalName="getFunctionName"]/> </property> <method name= "MethodName" [internalName="FunctionName"]> <parameter name="ParameterID"/> </method> <event name="Name" [dispid="DispID"]/> </public> <resource id="ResourceID"> Строка или число </resource> <object id="ObjID" [classld="clsid:GUID"|progid="ProgID"]/> <reference [object="ProgiD"|guid="typelibGUID"][version="version"]/> <script language="language"> <![CDATA[ Код сценария ]]> </script> </component> Другие компоненты </package> Несколько замечаний относительно количества вхождений различных XML-элементов из листинга 10.1 в WSC-файл: ? элемент <package>может содержать один или несколько элементов <component>; ? элемент <component>должен содержать один элемент <registration>и один элемент <public>; ? элемент <public>может содержать один или несколько элементов <property>, <method>или <event>. Обязательными для создания компонента-сценария являются элементы <component>, <registration>, <public>и <script>. Опишем теперь элементы XML, использующиеся в WSC-файлах, более подробно. Элементы WSC-файла В WSC-файлы можно вставлять комментарии двумя разными способами: с помощью элемента <!-- -->или элемента <comment>. Например: <!-- Первый комментарий --> или <comment> Второй комментарий </comment> Элементы <?xml?> и <![CDATA[]]> Напомним, что эти элементы являются стандартными для разметки W3C XML 1.0 (см. главу 3). Для того чтобы использовать символы кириллицы в файлах компонентов-сценариев, нужно обязательно в элементе <?xml?>указать атрибут encodingсо значением, соответствующим используемой кодировке, например: <?xml version="1.0" encoding="windows-1251"?> Элемент <package> Этот элемент необходим в тех WSC-файлах, в которых с помощью элементов <component>определено более одного компонента. В этом случае <package>является контейнером для элементов <component>. Если же в WSC-файле описан только один компонент, то элемент <package>можно не использовать. Элемент <component> Внутри элемента <component>описывается один компонент-сценарий (СОМ-объект). Необязательный атрибут idопределяет идентификатор объекта (это может понадобиться в том случае, когда в одном WSC-файле находится несколько СОМ-объектов). Элемент <registration> В элементе <registration>приводится информация, которая необходима для регистрации в системе компонента-сценария в качестве СОМ-объекта. Атрибуты progidи classidзадают соответственно программный идентификатор и глобальный код, с помощью которых компонент-сценарий может быть использован в других приложениях (например, progid="MyClass.MyObject"и classid="{424ac2bc-5732-4dea-be17-0211af99cd79}"). Из этих двух атрибутов обязательно должен быть указан хотя бы один (можно указать и оба). Если в элементе <registration>приведен только атрибут progid, то глобальный код (GUID) для описываемого объекта будет сгенерирован автоматически при регистрации объекта в системе. Рекомендуется, однако, явно указывать глобальный код объекта, т.к. в противном случае этот код может оказаться различным при регистрации объекта на разных машинах. Замечание С помощью атрибута descriptionможно задать краткое описание объекта, которое будет занесено в системный реестр при регистрации объекта. Атрибут versionпозволяет указать номер версии описываемого объекта. Этот номер позволяет запрашивать из приложения определенную версию СОМ-объекта (он должен быть указан через точку после программного идентификатора объекта, например "Myclass.MyObject.1"). С помощью элемента <script>внутри контейнера <registration>можно указать две функции, одна из которых будет вызываться при регистрации объекта в системе (эта функция должна иметь имя Register()), а другая — при удалении объекта из системы (эта функция должна иметь имя Unregister()). Элемент <public> В элементе <public>описываются те свойства, методы и события объекта, которые после его регистрации будут доступны извне другим приложениям (клиентам автоматизации). Другими словами, этот элемент является контейнером для элементов <property>, <method>и <event>. Элемент <property> Элемент <property>объявляет свойство СОМ-объекта, которое будет доступно для клиентов автоматизации. Атрибут nameопределяет имя этого свойства (в дальнейшем внутри элемента <script>должна быть объявлена глобальная переменная с тем же именем, с помощью которой можно будет изменять значение свойства). Объявляемое свойство может быть доступно либо только для чтения (внутри контейнера <property>указан только элемент <get>), либо только для записи (внутри <property>указан только элемент <put>), либо и для чтения и для записи (внутри <property>указаны как элемент <get>, так и элемент <put>). Атрибут internalNameв элементах <get>и <put>задает имена функций, которые будут использоваться для чтения и записи свойства соответственно (эти функции описываются внутри контейнера <script>). Если же атрибут internalNameне указан, то чтение (запись) свойства производится в функции с именем get_PropertyName(put_PropertуName), где PropertyName— имя свойства (атрибут <name>). Элемент <method> Элемент <method>объявляет метод СОМ-объекта, который будет доступен для внешних клиентов автоматизации. Атрибут nameопределяет имя этого метода. В дальнейшем, если не указан атрибут internalName, внутри контейнера <script>должна быть описана функция или процедура с таким же именем Задание атрибута internalNameпозволяет внутри контейнера <script>использовать для реализации метода функцию или процедуру с именем, отличным от значения аргумента name. Список параметров метода (если они имеются) задается внутри элемента <method>с помощью элементов <parameter>, каждый из которых должен содержать аргумент name, определяющий имя параметра. Элемент <event> Элемент <event>объявляет событие, которое может возникать в СОМ-объекте и обрабатываться клиентами автоматизации. Аргумент name, как обычно, определяет имя этого события. С помощью аргумента dispidможно указать числовой идентификатор интерфейса события. Этот идентификатор компилируется в библиотеку типов объекта и используется в клиентском приложении для обработки нужного события. Для того чтобы вызвать наступление события, внутри элемента <script>используется функция fireEvent()с именем нужного события в качестве параметра. Элементы <resource>, <object> и <reference> Элементы <resource>, <object>и <reference>имеют тот же смысл, что и в модели WS XML (см. описание этих элементов в главе 3). Элемент <script> В элементе <script>приводится сценарий на языках JScript или VBScript, который определяет поведение создаваемого СОМ-объекта — здесь нужно задать глобальные переменные, соответствующие объявленным в элементах <property>свойствам объекта, описать функции или процедуры для объявленных с помощью элементов <method>методов объекта и т.д. Перейдем теперь к рассмотрению конкретного примера, для которого мы подробно опишем создание компонента-сценария, регистрацию его в системе в качестве СОМ-объекта и использование этого объекта в JScript-сценарии. Пример: СОМ-объект для архивирования файлов Представим себе следующую ситуацию. Имеется несколько каталогов на жестком диске, в которых хранятся рабочие файлы разных пользователей. Необходимо каждый день с помощью программы-архиватора arj.exe делать архивы этих файлов в заданный каталог, при этом имя архивного файла должно соответствовать шаблону ппММДД.arj", где пп — уникальный для каждого пользователя префикс, ММ — текущий месяц, ДД — текущий день. Мы создадим компонент-сценарий DateArc.WSC, с помощью свойств и методов которого можно будет выполнить поставленную задачу. Начнем мы с того, что определимся, какие именно свойства и методы будет содержать создаваемый объект (табл. 10.1). Таблица 10.1. Свойства и методы объекта DateArc.WSC
Имея зарегистрированный в системе СОМ-объект с такими свойствами и методами, несложно написать сценарий (назовем его RunArj.js), в котором создавался бы экземпляр объекта DateArc.WSCи производилось с помощью метода FilesToArchiv()архивирование файлов из исходного в целевой каталог (листинг 10.2). Листинг 10.2. Архивирование файлов с помощью СОМ-объекта DateArc.WSC /********************************************************************/ /* Имя: RunArj.js */ /* Язык: JScript */ /* Описание: Архивирование файлов с помощью COM-объекта DateArc.WSC */ /********************************************************************/ //Объявляем переменные var DateArc, //Экземпляр объекта DateArc.WSC Result; //Результат выполнения метода FilesToArchiv() //Инициализируем константы для диалоговых окон var vbCritical=16,vbInformation=64; //Создаем объект WshShell WshShell = WScript.CreateObject("WScript.Shell"); //Создаем объект DateArc.WSC DateArc=WScript.CreateObject("DateArc.WSC"); DateArc.SFrom="D:\\1"; //Исходный каталог DateArc.SArch="D:\\2"; //Каталог, в который будут архивироваться //файлы DateArc.SPref="aa"; //Префикс для файл-архива DateArc.SMask="*.*"; //Маска, по которой будут отбираться файлы //для архивирования //Запускаем метод FilesToArchiv() Result=DateArc.FilesToArchiv(); if (!Result) //Если возникла ошибка, выводим соответствующее сообщение WshShell.Popup(DateArc.SErrMess, 0, "Архивирование файлов", vbCritical); else WshShell.Popup("Архивирование завершено успешно!", 0, "Архивирование файлов", vbInformation); /************* Конец *********************************************/ Создание макета файла DateArc.wsc с помощью Windows Script Component Wizard (JScript) Из листинга 10.1 можно понять, что создание компонента-сценария связано с написанием большого количества вспомогательного кода (нужно заполнить элементы <registration>, <property>, <method>и <events>, написать функции для чтения и записи каждого из свойств объекта и т.д). Поэтому мы воспользуемся специальным мастером для создания компонентов-сценариев Windows Script Component Wizard (эту программу можно свободно получить с сайта Microsoft http://msdn.microsoft.com/scripting). Первым шагом после запуска мастера является заполнение полей диалогового окна, представленного на рис. 10.1. Здесь нужно ввести имя создаваемого компонента ("DateArc"), имя файла с его описанием ("DateArc"), программный идентификатор ("DateArc.WSC"), версию компонента ("1.00") и каталог, в котором будет создан WSC-файл ("C:\WSC"). Рис. 10.1. Общая информация о создаваемом компоненте-сценарии На втором шаге работы мастера мы выберем, какой язык будет использоваться при написании сценария ("JScript"), и укажем, что при регистрации и работе объекта нужно выполнять проверку ошибок ("Error checking") (рис. 10.2). Рис. 10.2. Определение характеристик компонента-сценария Третий шаг работы мастера позволяет описать свойства создаваемого объекта. Здесь для каждого свойства мы указываем его имя (колонка "Name"), тип ("Read" — только чтение, "Write" — только запись, "Read/Write" — чтение и запись) и значение по умолчанию (колонка "Default") (рис. 10.3). Рис. 10.3. Задание свойств компонента-сценария На четвертом шаге описываются методы объекта. В нашем случае объект DateArc.WSCимеет единственный метод FilesToArchiv(), вызываемый без параметров (рис. 10.4). Рис. 10.4. Задание методов компонента-сценария На пятом шаге нам предлагается указать, какие события могут возникать в объекте. Для нашего компонента-сценария мы не будем задавать никаких событий (рис. 10.5). Рис. 10.5. Задание событий компонента-сценария Шестой шаг является заключительным в работе мастера. Здесь нам выдается вся информация о создаваемом объекте (рис. 10.6). После нажатия кнопки Finish в каталоге C:\WSC будет создан файл DateArc.wsc, приведенный в листинге 10.3. Рис. 10.6. Итоговая информация о создаваемом компоненте-сценарии Листинг 10.3. Файл DateArc.wsc, сгенерированный программой Windows Script Component Wizard (JScript) <?xml version="l.0"?> <component> <?component error="true" debug="false"?> <registration description="DateArc" progid="DateArc.WSC" version="1.00" classid="{424ac2bc-5732-4dea-bel7-0211af99cd79}"> </registration> <public> <property name="SFrom"> <get/> <put/> </property> <property name="SArch"> <get/> <put/> </property> <property name="SPref"> <get/> <put/> </property> <property name="SMask"> <get/> <put/> </property> <property name="SErrMess"> <get/> </property> <method name="FilesToArchiv"> </method> </public> <script language="JScript"> <![CDATA[ var description = new DateArc; function DateArc() { this.get_SFrom = get_SFrom; this.put_SFrom = put_SFrom; this.get_SArch = get_SArch; this.put_SArch = put_SArch; this.get_SPref = get_SPref; this.put_SPref = put_SPref; this.get_SMask = get_SMask; this.put_SMask = put_SMask; this.get_SErrMess = get_SErrMess; this.FilesToArchiv = FilesToArchiv; } var SFrom; var SArch; var SPref; var SMask; var SErrMess; function get_SFrom() { return SFrom; } function put_SFrom(newValue) { SFrom = newValue; } function get_SArch() { return SArch; } function put_SArch(newValue) { SArch = newValue; } function get_SPref() { return SPref; } function put_SPref(newValue) { SPref = newValue; } function get_SMask() { return SMask; } function put_SMask(newValue) { SMask = newValue; } function get_SErrMess(){ return SErrMess; } function FilesToArchiv() { return "Temporary Value"; } ]]> </script> </component> Как мы видим из листинга 10.3, при использовании в компоненте-сценарии языка JScript в результате работы мастера внутрь контейнера <script>помещаются: ? глобальные переменные, которые соответствуют объявленным в элементах <property>свойствам; ? заготовки функций с префиксами get_и put_, которые осуществляют чтение и запись свойств объекта; ? заготовки функций, которые соответствуют объявленным в элементах <method>методам. Кроме этого, создается экземпляр внутреннего объекта, содержащего те же свойства и методы, что были описаны внутри элемента <public>(переменная description). Имя этого внутреннего объекта совпадает с именем класса описываемого СОМ-объекта (в нашем случае это " DateArc"). Замечание Доработка объекта-сценария DateArc.wsc (JScript) Для получения нужного нам СОМ-объекта из сформированного с помощью Windows Script Component Wizard файла DateArc.wsc нужно выполнить несколько шагов. Во-первых, для того, чтобы использовать внутри описания СОМ-объекта символы кириллицы, необходимо добавить в директиву <?xml?>аргумент encoding="windows-1251"(без этого в сценарии не удастся даже написать по-русски комментарии): <?xml version="1.0" encoding="windows-1251"?> Во-вторых, в контейнер <registration>мы вставим элемент <script>с двумя функциями Register()и Unregister(), которые будут выводить на экран диалоговые окна с соответствующей информацией при регистрации компонента-сценария и его отключении соответственно: <script language="JScript"> <![CDATA[ var WshShell; //Инициализируем константы для диалоговых окон var vbInformation=64; function Register() { //Создаем объект WshShell WshShell = new ActiveXObject("WScript.Shell"); WshShell.Popup("Компонент зарегистрирован в системе",0, "Компонент для архивирования файлов",vbInformation); } function Unregister() { //Создаем объект WshShell WshShell = new ActiveXObject("WScript.Shell"); WshShell.Popup("Компонент удален из системы", 0, "Компонент для архивирования файлов",vbInformation); } ]]> </script> Затем нам понадобятся две дополнительные функции. Первая из них NowIs()формирует строку формата ММДД, где ММ — текущий месяц, ДД — текущий день: //Вспомогательная функция для символьного представления даты function NowIs() { var d, s="", s1=""; //Создаем объект Date (текущая дата) d=new Date(); //Выделяем номер месяца s+=(d.getMonth()+1); //Если месяц представляется одним символом, добавляем слева "0" if (s.length==1) s="0"+s; //Выделяем в дате день s1+=d.getDate(); //Если день представляется одним символом, добавляем слева "0" if (s1.length==1) s1="0"+s1; s+=s1; //Возвращаем сформированную строку return s; } Вторая функция CheckPath()будет проверять наличие исходного каталога и каталога для хранения архивных файлов. Для этого используется метод FolderExists()объекта FileSystemObject. Заметим, что сам объект FileSystemObjectнужно создавать не путем вызова метода CreateObjectобъекта WScript, а с помощью конструкции new ActiveXObject(): FSO=new ActiveXObject("Scripting.FileSystemObject"); т.к. в отличие от обычного сценария WSH в компоненте-сценарии нет встроенного объекта WScript. Если хотя бы один из каталогов не существует, функция CheckPath()запишет соответствующее сообщение в свойство SErrMessи вернет значение false, в противном случае функция CheckPath()возвращает значение true. //Проверка доступности каталогов function CheckPath() { var FSO; //Создаем объект FileSystemObject FSO=new ActiveXObject("Scripting.FileSystemObject"); //Проверяем доступность исходного каталога if (!FSO.FolderExists(SFrom)) { //Исходный каталог не существует //Формируем строку с информацией об ошибке SErrMess="Не найден исходный каталог "+SFrom; return false; } //Проверяем доступность каталога для архивирования if (!FSO.FolderExists(SArch)) { //Каталог для архивирования не существует //Формируем строку с информацией об ошибке SErrMess="Не найден каталог для хранения архивов "+SArch; return false; } //Если оба каталога существуют, возвращаем true return true; } Основной функцией, осуществляющей архивирование файлов, является FilesToArchiv(). В самом начале этой функции с помощью вызова CheckPath()проверяется наличие рабочих каталогов. Если хотя бы один из каталогов не существует, то выполнение FilesToArchiv()прерывается и возвращается значение false: if (!CheckPath()) return false; Затем создаются экземпляры объектов FileSystemObjectи WshShell: //Создаем объект FileSystemObject FSO = new ActiveXObject("Scripting. FileSystemObject"); //Создаем объект WshShell WshShell = new ActiveXObject("WScript.Shell"); Имя файла-архива формируется следующим образом: //Формируем имя файла-архива SFName=SPref+NowIs()+".arj"; Архиватор arj.exe мы будем запускать в отдельном командном окне, которое закроется после выполнения этой программы. Для этого мы сформируем командную строку SComLine, с помощью которой запускается вторичная копия командного процессора (путь к командному процессору хранится в переменной среды %COMSPEC%, вторичная копия вызывается с помощью ключа /с): SComLine="%COMSPEC% /с "; Синтаксис запуска arj.exe для создания архивного файла имеет следующий вид: arj.exe a Archiv Files где SComLine: SComLine+=" arj.exe a "+FSO.BuildPath(SArch, SFName) + " "; SComLine+= FSO.BuildPath(SFrom, SMask); Команды, записанные в SComLine, запускаются с помощью метода Runобъекта WshShell; код возврата сохраняется в переменной RetCode: RetCode = WshShell.Run(SComLine, 1, true); Равенство нулю переменной RetCodeозначает, что архивирование выполнено без ошибок — в этом случае функция FilesToArchiv()возвращает true. Если же при выполнении arj.exe возникла ошибка (переменная RetCodeне равна нулю), то ее код вносится в сообщение об ошибке (свойство SErrMess): //Анализируем код возврата для arj.exe if (0==RetCode) //Выполнение arj.exe завершилось без ошибок return true; else { //Формируем строку с информацией об ошибке SErrMess="Ошибка ARJ.EXE! Код "+RetCode; return false; } Полностью содержимое файла DateArc.wsc приведено в листинге 10.4. Листинг 10.4. СОМ-объектDateArc.WSC(JScript) <?xml version="1.0" encoding="windows-1251"?> <component> <registration description="DateArc" progid="DateArc.WSC" version="1.00" classid="{424ac2bc-5732-4dea-be17-0211af99cd79}"> <script language="JScript"> <![CDATA[ var WshShell; //Инициализируем константы для диалоговых окон var vbInformation=64; function Register() { //Создаем объект WshShell WshShell = new ActiveXObject("WScript.Shell"); WshShell.Popup("Компонент зарегистрирован в системе",0, "Компонент для архивирования файлов",vbInformation); } function Unregister() { //Создаем объект WshShell WshShell = new ActiveXObject("WScript.Shell"); WshShell.Popup("Компонент удален из системы",0, "Компонент для архивирования файлов",vbInformation); } ]]> </script> </registration> <public> <property name="SFrom"> <get/> <put/> </property> <property name="SArch"> <get/> <put/> </property> <property name="SPref"> <get/> <put/> </property> <property name="SMask"> <get/> <put/> </property> <property name="SErrMess"> <get/> </property> <method name="FilesToArchiv"> </method> </public> <script language="JScript"> <![CDATA[ var description = new DateArc; //Конструктор объекта DateArc function DateArc() { //Объявляем свойства объекта DateArc this.get_SFrom = get_SFrom; this.put_SFrom = put_SFrom; this.get_SArch = get_SArch; this.put_SArch = put_SArch; this.get_SPref = get_SPref; this.put_SPref = put_SPref; this.get_SMask = get_SMask; this.put_SMask = put_SMask; this.get_SErrMess = get_SErrMess; //Объявляем метод FilesToArchiv this.FilesToArchiv = FilesToArchiv; } var SFrom, //Исходный каталог для архивирования SArch, //Каталог, в котором будет создаваться архив SPref, //Префикс файла SMask, //Маска, по которой отбираются файлы для //архивирования SErrMess; //Текст сообщения об ошибке //Чтение и запись свойства SFrom function get_SFrom() { return SFrom; } function put_SFrom(newValue) { SFrom = newValue; } //Чтение и запись свойства SArch function get_SArch() { return SArch; } function put_SArch(newValue) { SArch = newValue; } //Чтение и запись свойства SPref function get_SPref() { return SPref; } function put_SPref(newValue) { SPref = newValue; } //Чтение и запись свойства SMask function get_SMask() { return SMask; } function put_SMask(newValue) { SMask = newValue; } //Чтение свойства SErrMess function get_SErrMess() { return SErrMess; } //Вспомогательная функция для символьного представления даты function NowIs() { var d, s="", s1=""; //Создаем объект Date (текущая дата) d=new Date(); //Выделяем номер месяца s+=(d.getMonth()+1); //Если месяц представляется одним символом, добавляем слева "0" if (s.length==1) s="0"+s; //Выделяем в дате день s1+=d.getDate(); //Если день представляется одним символом, добавляем слева "0" if (s1.length==1) s1="0"+s1; s+=s1; //Возвращаем сформированную строку return s; } //Проверка доступности каталогов function CheckPath() { var FSO; //Создаем объект FileSystemObject FSO=new ActiveXObject("Scripting.FileSystemObject"); //Проверяем доступность исходного каталога if (!FSO.FolderExists(SFrom)) { //Исходный каталог не существует //Формируем строку с информацией об ошибке SErrMess="Не найден исходный каталог "+SFrom; return false; } //Проверяем доступность каталога для архивирования if (!FSO.FolderExists(SArch)) { //Каталог для архивирования не существует //Формируем строку с информацией об ошибке SErrMess="Не найден каталог для хранения архивов "+SArch; return false; } //Если оба каталога существуют, возвращаем true return true; } //Архивирование файлов из исходного каталога function FilesToArchiv() { var WshShell,SComLine,RetCode,SFName,FSO; //Если хотя бы один из каталогов не существует, возвращаем false if (!CheckPath()) return false; //Создаем объект FileSystemObject FSO=new ActiveXObject("Scripting.FileSystemObject"); //Создаем объект WshShell WshShell = new ActiveXObject("WScript.Shell"); //Формируем имя файла-архива SFName=SPref+NowIs()+".arj"; //Формируем командную строку для запуска архиватора arj.exe SComLine="%COMSPEC% /c arj.exe a "; SComLine+=FSO.BuildPath(SArch,SFName)+" "; SComLine+=FSO.BuildPath(SFrom,SMask); //Запускаем архиватор arj.exe RetCode = WshShell.Run(SComLine, 1, true); //Анализируем код возврата для arj.exe if (0==RetCode) //Выполнение arj.exe завершилось без ошибок return true; else { //Формируем строку с информацией об ошибке SErrMess="Ошибка ARJ.EXE! Код "+RetCode; return false; } } ]]> </script> </component> Регистрация файла DateArc.wsc в качестве СОМ-объекта После написания текста объекта-сценария нужно внести информацию о нем в системный реестр, т.е, зарегистрировать объект. Это можно сделать несколькими способами, самый простой из которых заключается в следующем. Нужно выделить в Проводнике Windows необходимый WSC-файл с компонентом-сценарием (в нашем случае это файл DateArc.wsc в каталоге C:\WSC), щелкнуть правой кнопкой мыши и в появившемся контекстном меню выбрать пункт Подключить (Register) (рис. 10.7). Рис. 10.7. Контекстное меню, сопоставленное расширению WSC После этого необходимая информация запишется в реестр и выполнится функция Register(), которая описана в файле DateArc.wsc внутри элемента <registration>, в результате чего на экран будет выведено диалоговое окно, показанное на рис. 10.8. Рис. 10.8. Информация о регистрации компонента-сценария DateArc.WSC В системном реестре данные о регистрируемом объекте DateArc.WSCзаносятся в две ветви: HKEY_LOCAL_MACHINEи HKEY_CLASSES_ROOT. В разделе HKEY_LOCAL_MACHINE\SOFTWARE\Classesсоздается новый подраздел DateArc.WSCсо значением по умолчанию " DateArc". В подразделе DateArc.WSCв параметр CLSIDзаписывается глобальный код объекта DateArc.WSC— "{424AC2BC-5732-4DEA-BE17-0211AF99CD79}" (рис. 10.9). Рис. 10.9. Информация о зарегистрированном объекте DateArc.WSC в ветви HKEY_LOCAL_MACHINE В разделе HKEY_CLASSES_ROOT\CLSIDсоздается новый подраздел, название которого совпадает с глобальным кодом объекта DateArc.WSC — "{424AC2BC-5732-4DEA-BE17-0211AF99CD79}". Значением по умолчанию для нового подраздела является "DateArc" (рис. 10.10). Рис. 10.10. Информация о зарегистрированном объекте DateArc.WSC в ветви HKEY_CLASSES_ROOT В новом разделе создаются, в свою очередь, еще несколько подразделов, значения которых очень важны для функционирования компонента-сценария в качестве СОМ-объекта (см. разд. "Технология Windows Script Components"). Эти разделы для нашего примера описаны в табл. 10.2. Таблица 10.2. Подразделы, создаваемые в разделе HKCR\CLSID \{424AC2BC-5732-4DEA-BE17-0211AF99CD79} при регистрации объекта
Отключается компонент-сценарий так же просто, как и регистрируется. Снова нужно выделить в Проводнике Windows WSC-файл, щелкнуть правой кнопкой мыши и в появившемся контекстном меню выбрать пункт Отключить (Unregister). При этом из системного реестра записи об этом объекте будут удалены, после чего выполнится функция Unregister()(рис. 10.11). Рис. 10.11. Информация об отключении компонента-сценария DateArc.WSC Реализация объекта DateArc.wsc на VBScript Различие между компонентами-сценариями, написанными на языках JScript и VBScript, проявляется только в секции <script>WSC-файлов. Во-первых, естественным образом меняется синтаксис описанных внутри контейнера <script>функций. Во-вторых, в WSC-файле, написанном с помощью VBScript, отсутствует описание внутреннего объекта, который генерируется программой Windows Script Component Wizard и имеет поля и методы, совпадающие с объявленными внутри элемента <public>(см. листинг 10.3). Объяснение этому очень простое — в VBScript нельзя создавать свои внутренние объекты. Полностью содержимое файла DateArcVB.wsc, который реализует СОМ-объект DateArc.WSCс помощью VBScript, приведено в листинге 10.5. Листинг 10.5. СОМ-объект DateArc.WSC (VBScript) <?xml version="1.0" encoding="windows-1251"?> <component> <registration description="DateArc" progid="DateArc.WSC" version="1.00" classid="{424ac2bc-5732-4dea-be17-0211af99cd79}"> <script language="VBScript"> <![CDATA[ Dim WshShell Function Register() 'Создаем объект WshShell Set WshShell = CreateObject("WScript.Shell") WshShell.Popup "Компонент зарегистрирован в системе",0,_ "Компонент для архивирования файлов",vbInformation End Function Function Unregister() 'Создаем объект WshShell Set WshShell = CreateObject("WScript.Shell") WshShell.Popup "Компонент удален из системы",0,_ "Компонент для архивирования файлов",vbInformation End Function ]]> </script> </registration> <public> <property name="SFrom"> <get/> <put/> </property> <property name="SArch"> <get/> <put/> </property> <property name="SPref"> <get/> <put/> </property> <property name="SMask"> <get/> <put/> </property> <property name="SErrMess"> <get/> </property> <method name="FilesToArchiv"> </method> </public> <script language="VBScript"> <![CDATA[ Dim SFrom 'Исходный каталог для архивирования Dim SArch 'Каталог, в котором будет создаваться архив Dim SPref 'Префикс файла Dim SMask 'Маска, по которой отбираются файлы для 'архивирования Dim SErrMess 'Текст сообщения об ошибке 'Чтение и запись свойства SFrom Function get_SFrom() get_SFrom = SFrom End Function Function put_SFrom(newValue) SFrom = newValue End Function 'Чтение и запись свойства SArch Function get_SArch() get_SArch = SArch End Function Function put_SArch(newValue) SArch = newValue End Function 'Чтение и запись свойства SPref Function get_SPref() get_SPref = SPref End Function Function put_SPref(newValue) SPref = newValue End Function 'Чтение и запись свойства SMask Function get_SMask() get_SMask = SMask End Function Function put_SMask(newValue) SMask = newValue End Function 'Чтение свойства SErrMess Function get_SErrMess() get_SErrMess = SErrMess End Function 'Вспомогательная функция для символьного представления даты Function NowIs() Dim d,s,s1 s="" s1="" 'Определяем текущую дату d=Date() 'Выделяем номер месяца s=s & Month(d) 'Если месяц представляется одним символом, добавляем слева "0" If Len(s)=1 Then s="0" & s End If 'Выделяем в дате день s1=s1 & Day(d) 'Если день представляется одним символом, добавляем слева "0" If Len(s1)=1 Then s1="0" & s1 End If s=s & s1 'Возвращаем сформированную строку NowIs=s End Function 'Проверка доступности каталогов Function CheckPath() Dim FSO 'Создаем объект FileSystemObject Set FSO=CreateObject("Scripting.FileSystemObject") 'Проверяем доступность исходного каталога If Not FSO.FolderExists(SFrom) Then 'Исходный каталог не существует 'Формируем строку с информацией об ошибке SErrMess="Не найден исходный каталог " & SFrom CheckPath=false End If 'Проверяем доступность каталога для архивирования If Not FSO.FolderExists(SArch) Then 'Каталог для архивирования не существует 'Формируем строку с информацией об ошибке SErrMess="Не найден каталог для хранения архивов " & SArch CheckPath=false End If 'Если оба каталога существуют, возвращаем true CheckPath=true End Function 'Архивирование файлов из исходного каталога Function FilesToArchiv() Dim WshShell,SComLine,RetCode,SFName,FSO 'Если хотя бы один из каталогов не существует, возвращаем false If Not CheckPath() Then FilesToArchiv=false End If 'Создаем объект FileSystemObject Set FSO=CreateObject("Scripting.FileSystemObject") 'Создаем объект WshShell Set WshShell=CreateObject("WScript.Shell") 'Формируем имя файла-архива SFName=SPref & NowIs() & ".arj" 'Формируем командную строку для запуска архиватора arj.exe SComLine="%COMSPEC% /c arj.exe a " SComLine=SComLine & FSO.BuildPath(SArch,SFName)+" " SComLine=SComLine & FSO.BuildPath(SFrom,SMask) 'Запускаем архиватор arj.exe RetCode = WshShell.Run(SComLine, 1, true) 'Анализируем код возврата для arj.exe If 0=RetCode Then 'Выполнение arj.exe завершилось без ошибок FilesToArchiv=true Else 'Формируем строку с информацией об ошибке SErrMess="Ошибка ARJ.EXE! Код " & RetCode FilesToArchiv=false End If End Function ]]> </script> </component> |
|
|||||||||||||||||||||||||||||||||||||||||||
Главная | Контакты | Нашёл ошибку | Прислать материал | Добавить в избранное |
|||||||||||||||||||||||||||||||||||||||||||||
|