Онлайн библиотека PLAM.RU


  • Технология Windows Script Components
  • Схема WSC XML
  • Элементы WSC-файла
  • Элементы <?xml?> и <![CDATA[]]>
  • Элемент <package>
  • Элемент <component>
  • Элемент <registration>
  • Элемент <public>
  • Элемент <property>
  • Элемент <method>
  • Элемент <event>
  • Элементы <resource>, <object> и <reference>
  • Элемент <script>
  • Пример: СОМ-объект для архивирования файлов
  • Создание макета файла DateArc.wsc с помощью Windows Script Component Wizard (JScript)
  • Доработка объекта-сценария DateArc.wsc (JScript)
  • Регистрация файла DateArc.wsc в качестве СОМ-объекта
  • Реализация объекта DateArc.wsc на VBScript
  • Глава 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) для описываемого объекта будет сгенерирован автоматически при регистрации объекта в системе. Рекомендуется, однако, явно указывать глобальный код объекта, т.к. в противном случае этот код может оказаться различным при регистрации объекта на разных машинах.

    Замечание

    Глобальный код объекта может быть сгенерирован с помощью описанной ниже программы Windows Script Component Wizard.

    С помощью атрибута

    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

    Название Свойство/метод Режим доступа Описание
    SFrom
    Свойство Чтение/запись Исходный каталог для архивирования
    SArch
    Свойство Чтение/запись Каталог, в котором хранятся архивные файлы
    SPref
    Свойство Чтение/запись Префикс файла-архива
    SMask
    Свойство Чтение/запись Маска, по которой отбираются файлы для архивирования
    SErrMess
    Свойство Чтение Текст сообщения об ошибке
    FilesToArchiv()
    Метод   Метод, осуществляющий архивирование файлов

    Имея зарегистрированный в системе СОМ-объект с такими свойствами и методами, несложно написать сценарий (назовем его 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
    ").

    Замечание

    Создаваемый мастером внутренний объект нужен только в иллюстративных целях, т.к. здесь наглядно видно, какие именно свойства и методы будет предоставлять клиентам автоматизации компонент-сценарий. Если убрать из контейнера

    <script>
    описание внутреннего объекта, это никак не скажется на функционировании объекта-сценария.

    Доработка объекта-сценария 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

    где

    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} при регистрации объекта

    DateArc.WSC

    Название Значение по умолчанию Описание
    InprocServer32
    "F:\WINDOWS\System32\scrobj.dll" Полный путь к оболочке компонентов-сценариев scrobj.dll
    ProgID
    "DateArc.WSC.1.00" Программный идентификатор объекта, включающий номер версии
    ScriptletURL
    "file://C:\WSC\DateArc.wsc" Полный путь к WSC-файлу
    VersionIndependentProgID
    "DateArc.WSC" Программный идентификатор объекта без номера версии

    Отключается компонент-сценарий так же просто, как и регистрируется. Снова нужно выделить в Проводнике 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>
     









    Главная | Контакты | Нашёл ошибку | Прислать материал | Добавить в избранное

    Все материалы представлены для ознакомления и принадлежат их авторам.