Обзор скриплет - технологии

Евгений Койнов

Введение

Скриплет - это новая технология позволяющая создавать COM компоненты средствами простых в использования языков сценариев, для этого подходит любой язык сценариев поддерживающий MS ActiveX Scripting интерфейс. Скриплет появился в 1997 году с выходом в свет Internet Explorer 4.0 и изначально был ориентирован на создание UI (user-interface) компонент многократного использования для Web страниц. Все что необходимо было знать для создания скриплета - это DHTML и какой-нибудь язык сценариев (JScript, VBScript). Т. к. этот скриплет базировался на DHTML и использовался в HTML документах, то он получил название DHTML скриплет. DHTML скриплет обладает богатыми возможностями для создания компонент пользовательского интерфейса, но не обеспечивает многоцелевого назначения компонентной архитектуры вне браузера. Для снятия этого ограничения был разработан серверный скриплет, далее именуемый просто скриплетом.

В результате мы имеем два варианта:

  1. DHTML скриплет, базирующийся на DHTML и используемый для создания UI компонент.
  2. Скриплет основанный на XML и языке сценариев, являющийся полноценной COM компонентой, о котором и пойдет речь в данном обзоре.

Что такое скриплет?

Скриплет является COM компонентой реализованной на XML (eXtensible Markup Language) и языке сценариев. XML используется для построения структуры скриплета (определения типа COM компоненты, ее методов, свойств, инициируемых событий, и т. д.), а код на языке сценариев обеспечивает функциональность.

Что касается скриплетов, то это полноценные COM компоненты и могут использоваться для решения широкого класса задач, как то:

Как скриплет работает?

Скриплет технология состоит из:

  1. Скриплет run-time (Scrobj.dll), в COM терминологии являющийся in - proc сервером для скриплетов.
  2. Interface handler, являющийся pre-compiled компонентой, реализующей различные COM интерфейсы. Разные interface handler ориентированы на работу с разными типами COM компонент.

Самые часто используемые interface handler включая COM Automation, Event и, DHTML Behavior interface handler уже встроены в скриплет run-time.

Вся сложность создания COM компонент, включая реализацию таких стандартных COM интерфейсов как IUnknown, встроена в interface handler. Скриплет содержит только код, обеспечивающий функциональность COM компоненты, и в сочетании с тем, что этот код реализуется на простом в изучении языке сценариев, скриплет - технология является самым простым и прозрачным способом создания COM компонент. Вы знаете, что компонента должна делать - вы создаете соответствующий скрипт, остальное забота run-time окружения. После создания скриплета вы можете использовать его как полноценную COM компоненту.

Создание скриплета

Файл описывающий скриплет(*.sct) - это XML файл, очень похожий на HTML, но содержащий специфические таги определяющие скриплет и его поведение. Остановимся поподробнее на создании скриплета. Скриплет содержит следующие элементы:

  1. <scriplet> - таг ограничивающий определение скриплета.
  2. <registration> - элемент содержащий информацию необходимую для регистрации скриплета как COM компоненты. Этот элемент может быть необязательным, если использующее скриплет приложение, например Internet Explorer, не использует напрямую реестр Windows при создании экземпляра скриплета.
  3. <implements> - содержит объявление об используемых interface handlers для данного скриплета, определяющее к какому типу COM компонент будет принадлежать скриплет или какие дополнительные возможности предполагается использовать, например Event interface handler. В зависимости от COM типа в <implements> определяются свойственные ему методы, реализация которых ложится на вас. Предположим, вы объявляете об использовании Automation handler, определяющим ваш скриплет как COM Automation компоненту и тогда внутри <implements>, кроме объявления типа: <implements type=Automation > определяются те методы и свойства, которые вы хотите сделать доступными.
  4. <script> содержит код реализующий логику скриплета, зависящий от того к какому типу COM компонент ваш скриплет принадлежит. Если вы создаете COM Automation, то в <script> реализуются описанные в <implements> методы и свойства. Каркас скриплета представляет из себя нечто подобное:
    <?scriptlet validate="true" error="true" debug="true"?>
       <scriptlet>
          <registration progid="progid" description="description"
                               version="version" clsid="{classid}">
          <implements type=COMhandlerName id=internalName>
             <property name="name"/>
             <method name="name"/>
          </implements>
          <script language="VBScript">
             Function method()
                'script here End Function
          </script>
          <script language="JavaScript">
             function method() {
                // script here
             }
          </script>
      </scriptlet>

Иногда необходимо чтобы скриплет был зарегистрирован. Для регистрации скриплета можно воспользоваться программой Regsvr32.exe или выбрав пункт Register по правому нажатию кнопки мыши на файле *.sct.

Для того чтобы облегчить приложению, использующему скриплеты возможность узнать интерфейс скриплета, имеется возможность создать библиотеку типов. Библиотека типов содержит информацию о методах, свойствах и инициируемых событиях скриплета, а также количестве параметров необходимых для вызова методов. Для создания библиотеки типов необходимо выбрать пункт Generate Type Library в меню по правому нажатию кнопки мыши. Библиотека типов (*.tlb) создается в той же папке с именем скриплета и регистрируется в реестре Windows.

По умолчанию при выполнении скриплета не выдается никаких сообщений об ошибках. Но можно включить режим, при котором отслеживаются синтаксические ошибки, проверяется корректность использования XML и появляется возможность отладки скриплета средствами script debugger. Для этого в элементе <?scriptlet?> - предусмотрены следующие опции:

  1. validate - при присвоении true, выполняется проверка XML элементов на корректность использования и синтаксические ошибки.
  2. error - при присвоении true, позволяет получать сообщения об ошибках времени исполнения.
  3. debug - при присвоении true, позволяет отлаживать скриплет с помощью script debugger.

Если элемент <?scriptlet?> не включен в файл, то все опции устанавливаются в false.

События

По умолчанию скриплет не вызывает событий, которые могут быть обработаны в контейнере. Однако, реализуя Event interface handler можно добавлять события в скриплет. После этого появляется возможность инициировать события из скриплета в любое время. Для того чтобы добавить событие необходимо:

  1. В элементе <implements> объявить об использовании Event interface handler, обеспечивающий механизм генерации событий.
  2. Объявить о каждом событии, которое вы хотите иметь возможность вызывать.
  3. Создать библиотеку типов для скриплета, чтобы контейнер имел возможность получить список возможных событий.
    <implements type="Event" id="scriptlet1">
     <event name="event1"/>
     <event name="event2"/>
    </implements>

В COM программировании уведомление о событиях происходит через dispatch идентификатор (dispid) - целое число, определяющее событие инициируемое компонентой. Dispid компилируется в библиотеку типов и затем используется приложением для связи с событием. В процессе создания библиотеки типов dispid создается автоматически, но вы можете определить его сами:

<event name="event1" dispid=22 />.

После определения события можно его вызывать с помощью метода fireEvent(), например:

scriplet1.fireEvent("event2");

Пример скриплета

В качестве примера создадим скриплет "Employee", хранящий ID сотрудника, его заработную плату, имеющий метод повышения зарплаты и реализующим одно событие. Определим read-only поле "Salary", read-write поле "EmpID", метод "RaiseSalary" повышающий зарплату и событие "Enough", когда зарплата превышает какой-то порог :). В нашем случае скриплет является COM Automation компонентой. Так как в свойстве "Salary" реализован только метод get_, то свойство доступно только для чтения.

<scriptlet>
<Registration ProgID="Employee.Scriptlet"/>
<implements id=Automation type=Automation>
   <property name=Salary>
      <get/>
   </property>
   <property name=EmployeeNumber internalname=EmpID>
      <get/>
      <put/>
   </property>
   <method name=RaiseSalary>
      <PARAMETER name=Percentage/>
   </method>
</implements>

<implements type="Event" id="scriptlet1">
   <event name="Enough"/>
</implements>

<script language=JScript>
   var Salary
   var EmpID
   
   Salary = 10000
   function get_EmpID() {
      return EmpID;
   }
   
   function put_EmpID(newValue) {
        EmpID = newValue;
   }   

   function get_Salary() {
      return Salary;
   }

   function RaiseSalary(Percentage) {
      increase = Salary * (Percentage/100);
      Salary = Salary + increase;
      If Salaty > 25000
         scriplet1.fireEvent("Enough");
   }
</script>
</scriptlet>