Сообщений 2 Оценка 155 Оценить |
Введение Создание инсталляции Описание содержимого инсталляционного пакета On-line ресурсыОписание интерфейса пользователя Описание операций, выполняемых во время инсталляции Заключение |
Технология Microsoft Windows Installer в настоящий момент является стандартом de-facto в области распространения программного обеспечения, и в распоряжении разработчиков имеется довольно широкий круг инструментов для создания инсталляционных пакетов формата msi.
С одной стороны представлены коммерческие продукты с большими возможностями, встроенными скриптовыми языками и солидным набором мастеров создания всего и вся - такие, как Wise Installer и InstallShield Studio. С другой, существует масса небольших, но порою весьма качественных инсталляторов (к примеру, Inno Setup) для создания ординарных инсталляций с помощью несложного графического интерфейса. Но среди всех подобных программ особое место занимает продукт под названием MakeMsi, созданный австралийцем Денисом Барисом (Dennis Bareis).
Дело в том, что MakeMsi практически не имеет графического интерфейса (если не считать интеграцию в контекстное меню проводника) и представляет собой набор макроопределений на языке REXX, которые с помощью специального транслятора преобразовываются в скрипт на Visual Basic, создающий требуемый msi-пакет. На первый взгляд сложно, но при детальном знакомстве с программой становится ясно, что подобный подход обладает рядом существенных преимуществ.
Во-первых, это традиционная форма написания программы. Скрипт для создания msi-пакета именно пишется, так как представляет собой простой текстовый файл. Этот факт весьма примечателен, так как дает возможность использовать комментарии, системы контроля версий и всеми любимую технологию «Copy/Paste». К тому же, общение с компьютером посредством консоли всегда идет человеку на пользу ("Вторая сигнальная система и мышь" :-).
Во-вторых, полный контроль над базой данных создаваемого пакета. MakeMsi позволяет работать напрямую со строками таблиц базы данных пакета при помощи SQL-подобных конструкций.
В-третьих, возможность модификации скриптов из состава MakeMsi. Если вас что-то не устраивает в работе продукта, вы можете изменить процесс формирования msi-пакета путем редактирования существующих макросов.
Для облегчения процесса создания инсталляции в состав пакета входят два файла-заготовки – company.mm и dept.mm, на основе которых разработчику предлагается сформировать шаблоны для создания инсталляций в рамках организации в целом и отдельных ее подразделений в частности. В дополнение к ним имеется файл uisample.msi, содержащий пользовательский интерфейс для типовой инсталляции –диалог приветствия, текст лицензии, выбор типа установки, выбор компонентов и так далее. Поэтому простейший пример создания полноценного инсталляционного пакета выглядит более чем компактно:
#include "DEPT.MMH" ;--- Create INSTALLDIR ------------------------------------------------------ <$DirectoryTree Key="INSTALLDIR" Dir="c:\program files\TryMe (makemsi sample)" CHANGE="\"> ;--- Add the files (components generated) ----------------------------------- <$Files "TryMe.rtf" DestDir="INSTALLDIR"> |
Как видно из примера, инсталляция описывается с помощью набора специальных тегов. Эти теги могут использоваться как парно – открывающий и закрывающий <$имя_тега>текст<$/имя_тега>, так и одиночно – <$имя_тега текст>. Все они подробно описаны в прилагающейся справке, поэтому рассматривать мы здесь будем не синтаксис каждого тега, а общую логику их совместного использования.
В общем случае процесс создания инсталляции состоит из трех основных этапов:
Данные об устанавливаемых программах хранятся в специальных таблицах базы данных msi-пакета, представленных на рисунке 1.
Рисунок 1.
Из представленной схемы, на которой для упрощения картины представлены лишь основные таблицы, видно, что приложение (product в терминологии Microsoft) состоит из опций (таблица Feature), имеющих иерархическую структуру, которые, в свою очередь, делятся на компоненты (таблица Component).
При этом компонент может принадлежать более чем к одной опции благодаря наличию таблицы FeatureComponents. Компонент является неделимой единицей, которой оперирует служба MS Installer в процессе установки, удаления или восстановления приложения. В состав компонента могут входить файлы (таблица File) и операции с реестром Windows (таблица Registry и RemoveRegistry).
ПРИМЕЧАНИЕ Помимо этого, компонент может содержать переменные окружения, COM-объекты, DCOM-приложения, источники данных ODBC и другие объекты, но их рассмотрение выходит за рамки данной статьи. |
Для заполнения вышеперечисленных таблиц предназначены одноименные теги. Логика их использования достаточно проста, поэтому сразу перейдем к примеру:
;--- Установка кодовой страницы ------------------------------------------- <$CodePage "1251"> ;--- Создание модуля ------------------------------------------------------ #( <$Feature "ClientFeature" Title="Консоль администратора" Description="Клиентское приложение" > #) ;--- Создание компонента -------------------------------------------------- <$Component "Client" Directory_="INSTALLDIR"> ;--- Добавление файла в состав компонента---------------------------------- <$File Source="Client.exe" RowKey="Client.exe" KeyPath="Y"> <$/Component> <$/Feature> <$Feature "ServerFeature" Title="Сервер" Description="Серверное приложение"> <$Feature "MonitorFeature" Title="Монитор" Description="Модуль контроля"> <$Component "Monitor" Directory_="INSTALLDIR"> <$File Source="Monitor.dll" RowKey="Monitor.dll" KeyPath="Y"> ;--- Регистрация COM-объекта ----------------------------------------------- <$SelfRegister "Monitor.dll"> <$/Component> <$/Feature> <$Component "Server" Directory_="INSTALLDIR"> <$File Source="Server.exe" RowKey="Server.exe" KeyPath="Y"> <$/Component> <$/Feature> |
СОВЕТ Для более наглядного форматирования используются операции конкатенации строк – конструкция «#(...#)» и обратный слеш в конце строки. |
Отображение структуры полученного инсталляционного пакета в диалоге выбора компонентов (CustomiseDlg) представлено на рисунке 2.
Рисунок 2.
Все достаточно просто, однако следует обратить внимание на некоторые детали.
Появился корневой модуль «Complete», который мы, вроде бы, не заказывали. Он создается по умолчанию в файле COMPANY.mmh в секции «Set up the "COMPLETE" feature». Иметь корневой модуль – дело, конечно, хорошее, но хотелось бы дать ему более подходящее название. Нет ничего проще, ведь COMPANY.mmh – это шаблон, который можно переделывать на свой вкус. Ищем в нем строку «@@T = 'Complete.<$ProductVersion>.<$ProdInfo.ProductName>'» и пишем в ней новое название корневого модуля. С другой стороны, бывают ситуации, когда корень в дереве выбора модулей не требуется. Это вариант также предусмотрен – необходимо только определить значение константы COMPANY_WANT_COMPLETE_FEATURE:
#define COMPANY_WANT_COMPLETE_FEATURE N
|
Рассмотрим подробнее тег <$Component>, который имеет ряд интересных параметров.
ПРИМЕЧАНИЕ В общем случае параметры тега имеют однозначное соответствие полям таблицы базы данных, поэтому термины «параметр» и «поле» далее по тексту используются как синонимы. |
Параметр KeyPath. Указывает на файл или каталог, принадлежащий компоненту, по существованию которого в дальнейшем служба MS Installer будет судить, установлен компонент или нет. Естественно, что два компонента не могут иметь одинаковое значение в этом поле. Если значение KeyPath равно NULL, то ключом для поиска компонента является каталог, указанный в поле Directory_. Рекомендуется создавать по одному компоненту на каждый устанавливаемый файл, так как если из двадцати динамических библиотек, входящих в ваш компонент, на диске сохранится только одна, но именно та, которая указана в значении KeyPath, компонент будет считаться установленным корректно и не будет обновлен при восстановлении приложения. Установить значение этого свойства можно либо непосредственно в теге <$Component KeyPath=«value»>, либо в теге <$File> с помощью конструкции KeyPath="Y". Во втором случае значением свойства станет имя файла, указанного в поле Source.
Параметр Attributes. Его значения с описаниями представлены в таблице 1.
Свойство | Значение | Описание |
---|---|---|
LocalOnly | 0 | Компонент может запускаться только при установке на жесткий диск. |
SourceOnly | 1 | Компонент может запускаться только с источника инсталляции. |
Optional | 2 | Компонент может запускаться как при установке на диск, так и из источника. |
RegistryKeyPath | 4 | Компонент представляет операции с реестром. |
SharedDllRefCount | 8 | При наличии этого атрибута MS Installer создаст в реестре ключи для подсчета ссылок на файлы компонента, считая компоненты разделяемыми библиотеками, и увеличит созданные счетчики на единицу. При отсутствии этого атрибута количество ссылок будет увеличено только для тех файлов, у которых счетчик ссылок уже существует. |
Permanent | 16 | Компонент не будет удален при деинсталляции приложения. |
ODBCDataSource | 32 | Компонент является источником данных ODBC. |
Transitive | 64 | Применяется для транзитивных компонентов. Предполагает, что при переустановке приложения, если компонент был установлен, то он будет удален и наоборот. |
NeverOverwrite | 128 | Компонент не будет переписан при установке или переустановке. При этом приложению не требуется регистрироваться как клиенту данного компонента. Применяется в основном для записей реестра. |
Для иллюстрации следующего параметра, Condition, представим себе гипотетическую задачу: устанавливаемый продукт в своей работе использует технологию DCOM. При установке на операционную систему Windows XP SP2 необходимо удостовериться, что брандмауэр разрешает использование соответствующего порта, так как по умолчанию порт 135 закрыт, равно как и большинство других. Для решения этой задачи может служить компонент следующего вида:
#( <$Component "XP_SP2_firewall_settings" Condition="VersionNT=501 AND ServicePackLevel=2" Attributes="RegistryKeyPath" > #) #( <$Registry HKEY="LOCAL_MACHINE" Key="SYSTEM\ControlSet001\Services\SharedAccess\Parameters\ FirewallPolicy\StandardProfile\GloballyOpenPorts\List" Name="135:TCP" Value="135:TCP:*:Enabled:DCOM" > #) <$/Component> |
Параметр Condition представляет собой логическое выражение, в качестве операндов которого могут использоваться следующие понятия:
Свойства (Properties). Используемые в данном случае литералы «VersionNT» и «ServicePackLevel» являются встроенными свойствами, инициализацией которых занимается непосредственно служба MS Installer. Полный список встроенных свойств можно найти в разделе MSDN «Platform SDK: Windows Installer» . Помимо встроенных свойств существуют еще и пользовательские свойства, которые хранятся в таблице Property и могут быть добавлены с помощью тега <$Property>. Свойства могут быть как доступными из командной строки (Public property), так и недоступными (Private). Это зависит от имени свойства – если имя состоит только из заглавных букв, то свойство считаются Public, иначе – Private.
Состояние модулей и компонентов. Таких состояний может быть пять:
Состояние (константы из MS Install SDK) | Значение | Описание |
---|---|---|
INSTALLSTATE_UNKNOWN | -1 | С модулем или компонентом не производилось никаких действий. |
INSTALLSTATE_ADVERTISED | 1 | Модуль будет установлен по требованию (для компонентов не применяется). |
INSTALLSTATE_ABSENT | 2 | Не установлен. |
INSTALLSTATE_LOCAL | 3 | Установлен на жесткий диск. |
INSTALLSTATE_SOURCE | 4 | Запускается с источника инсталляции. |
С помощью специальных префиксов, значения которых приведены в таблице 3, можно проверить, в каком состоянии находится модуль или компонент.
Тип аргумента | Префикс | Значение |
---|---|---|
Значение ключевого поля таблицы «Component” | $ | Текущее действие над компонентом. |
Значение ключевого поля таблицы «Component” | ? | Действие над компонентом, выполненное во время предыдущей инсталляции. |
Feature table key | & | Текущее действие над модулем. |
Feature table key | ! | Действие, выполненное над модулем во время предыдущей инсталляции. |
В качестве примера приведу условие, принимающее истинное значение при ранее локально установленном модуле ServerFeature без компонента Monitor и выборе пункта «Запускать с носителя» для модуля Client при текущей инсталляции: “!ServerFeature=3 AND ?Monitor=2 AND &Client=4”.
Переменные окружения. Для их использования применяется префикс «%». Например “%NUMBER_OF_PROCESSOR=2”.
Помимо управления одиночными записями, для более объемных операций с реестром существует тег <$RegistryImport>. С его помощью можно включить в состав инсталляции содержимое reg-файла. Особенностью его использования является то, что указанный файл должен иметь формат “REGEDIT4”. С помощью таких параметров, как CURRENT_USER, LOCAL_MACHINE и CLASSES_ROOT, можно указать, к какому компоненту будут принадлежать импортируемые записи:
<$Component "Client" ...> <$Component "Server" ...> <$RegistryImport "settings.reg" LOCAL_MACHINE="Server" CURRENT_USER="Client"> |
Еще один использованный в нашем примере тег – <$SelfRegister >. Он предназначен для добавления записи в таблицу SelfReg. В качестве параметра этот тег принимает значение из ключевого столбца таблицы File. В процессе инсталляции при выполнении стандартных действий SelfRegModules и SelfUnRegModules для всех файлов, перечисленных в таблице SelfReg, будет выполнен вызов соответственно функций DllRegisterServer и DllUnregisterServer.
Данные о пользовательском интерфейсе также хранятся в базе данных msi-пакета. Структура предназначенных для этого таблиц представлена на рисунке 3.
Рисунок 3
Интерфейс состоит из последовательности модальных диалогов (таблица Dialog), на которых расположены элементы управления (таблица Control). С каждым из элементов может быть ассоциировано одно или несколько событий (таблица ControlEvent), которые могут менять свои состояния (таблица ControlCondition) и взаимодействовать с другими элементами через подписку на их события (таблица EventMapping).
Входящий в состав пакета MakMsi файл UiSample.msi содержит стандартные диалоги, которых вполне достаточно для создания типовой инсталляции. Но иногда возникает потребность в изменении или расширении пользовательского интерфейса инсталляции.
Рассмотрим теги, предназначенные для манипуляций с диалогами.
<$DialogPreview "имя_диалога"> – позволяет просмотреть внешний вид диалога в процессе компиляции mm-файла. В названии диалога допускается использование символа «*» для обработки диалогов по шаблону. При отсутствии названия будут показаны все имеющиеся диалоги.
<$DialogRemove " имя_диалога "> – удаляет указанный диалог. Может использоваться только в скриптах, использующих в качестве основы файл UiSample.msi, и не предназначен для удаления первого и последнего диалога в последовательности.
<$Dialog> – создает новый диалог. В качестве иллюстрации использования данного тега рассмотрим пример настройки подключения к серверу БД в процессе инсталляции:
;--- Создание диалога ----------------------------------------------------- #( <$Dialog "Подключение к серверу БД" INSERT="WelcomeDlg" Description="Укажите параметры подключения" Dialog="ConnectionDialog" > #) ;--- Создание радиокнопок Radio Button ------------------------------------ #data 'RadioButton_SSPI' '1' 'Yes' '50' '2' 'No' '75' #data ;--- Создание полей ввода ------------------------------------------------- #( <$DialogEntry Property="SSPI" Label="Использовать Windows-идентификацию" Control="RB" > #) #( <$DialogEntry Property="UID" Label="Логин:" ToolTip="Введите имя пользователя (10 символов)" Max=10 Width=50 > #) #( <$DialogEntry Property="PWD" Label="Пароль:" ToolTip="Введите пароль (20 символов)" Max=20 Password=Y Width=50> <$/Dialog> #) |
Сформированный таким образом диалог показан на рисунке 4.
Рисунок 4.
Параметр Insert предназначен для указания места вставки нового диалога. Представляет собой строку вида «имя_предыдущего_диалога[-имя_следующего диалога]». По умолчанию в качестве следующего диалога устанавливается диалог выбора типа инсталляции (SetupTypeDlg).
Для идентификации диалога в таблице Dialog предназначен необязательный параметр Dialog. Если он не указан, значение ключевого поля для вставляемого диалога будет сформировано автоматически.
Элементы управления создаются с помощью тегов <$DialogEntry>, размещенных внутри тега <$Dialog>. С помощью перечисленных ниже параметров тега <$DialogEntry> можно реализовать достаточно сложный пользовательский интерфейс.
Параметр Label (обязательный) содержит текст подписи к компоненту. На рисунке 4 видно, что текст подписи к радио-кнопке выбора метода идентификации не выводится полностью. Для исправления этой ситуации предназначен макрос «DIALOGTEMPLATE_LABEL_COLUMN_WIDTH». В нашем случае достаточно задать ему значение 200:
#define DIALOGTEMPLATE_LABEL_COLUMN_WIDTH 200
|
Параметр Property (обязательный). Определяет пользовательское свойство, в котором будет сохранено значение элемента управления.
Параметр Control (необязательный). Определяет тип элемента управления. Значения этого параметра представлены в таблице 4.
Значение | Описание |
---|---|
EF | Поле ввода. Значение по умолчанию. |
XB[:False|True] | Флажок. После двоеточия имеется возможность указать значения связанного свойства при невыбранном и выбранном (именно в таком порядке) состоянии элемента. По умолчанию используются значения 0 и 1. |
ME:EditMask | Поле ввода по шаблону. Для задания шаблона используются следующие символы:“#” – цифра;“?” – цифра или буква;“=”, “.”, “\” и другие не цифробуквенные символы – сепараторы для разделения вводимого значения на отдельные поля ввода;“<text>” – при использовании этой конструкции поле ввода становиться неизменяемым, а все что находиться вне блока “<text>” не отображается; |
CB | Комбинированный список. Для его создания необходимо с помощью тега #data определить структуру данных, состоящую из двух столбцов. Первый предназначен для значения свойства, второй – для отображаемого текста. Допускает ввод новых значений пользователем. |
CL | То же, что и CB, но допускает только выбор из списка. |
RB | Переключатель. Для его создания необходимо с помощью тега #data определить структуру данных, состоящую из четырех столбцов. Первый предназначен для значения свойства, второй – для отображаемого текста, третий определяет позицию для размещения следующей кнопки (если этот параметр не указан или равен "", то кнопка будет располагается на следующей строке), четвертый содержит текст всплывающей подсказки. |
Параметр Max (необязательный). Определяет максимальное количество символов, допустимое в поле ввода.
Параметр Integer. Ограничивает вводимое значение только цифрами.
Для каждого элемента диалога генерируется функция проверки корректности. По умолчанию проверяется только наличие значения в поле. Для организации более сложных проверок предназначены параметры Blank (отключает проверку на обязательный ввод значения) и MatchRe (проверка с помощью регулярных выражений).
Необязательные параметры Password, Trim, Case, X и Y в комментариях не нуждаются.
Для придания законченности нашему примеру неплохо было бы отключать возможность ввода логина и пароля при выборе Windows-идентификации. Для этого необходимо использовать таблицу ControlCondition. Для работы с ней нет специальных тегов, поэтому добавим требуемые записи в помощью <$Table> и <$Row>:
<$Table "ControlCondition"> <$Row Dialog_="ConnectionDialog" Control_="Entry.2" Action="Enable" \ Condition="SSPI=2"> <$Row Dialog_="ConnectionDialog" Control_="Entry.2" Action="Disable" \ Condition="SSPI=1"> <$Row Dialog_="ConnectionDialog" Control_="Entry.3" Action="Enable" \ Condition="SSPI=2"> <$Row Dialog_="ConnectionDialog" Control_="Entry.3" Action="Disable" \ Condition="SSPI=1"> <$/Table> |
Тег <$Table>, кроме имени таблицы, имеет всего один необязательный параметр Create. Значение “Y” подразумевает создание новой таблицы. По умолчанию этот параметр имеет значение “N”. При желании базу данных инсталляционного пакета можно дополнить собственными таблицами. Предположим, что необходимо добавить второй поток (естественно, только для файловой системы NTFS) к устанавливаемым файлам с различного рода служебной информацией. Для этого создадим новую таблицу, связанную с таблицей File, которая и будет содержать необходимые данные:
<$TableDefinition "FileStream"> <$Column "File_" TYPE="s72" Key="Y"> <$Column "Info" TYPE="S254"> ;;максимальная длина символьных полей <$/TableDefinition> <$Table "FileStream" Create="Y"> #( <$Row @Validate="" File_="Client.exe" Info="Что может быть во втором потоке exe-файла?" > #) #( <$Row @Validate="" File_="Server.exe" Info="Например, номер лицензии, для организации контроля над распространением продукта" > #) <$/Table> |
Комментариев в этом примере требует только параметр TYPE тега <$Column >. Его значение состоит из буквы, обозначающей тип поля, и числа, определяющего длину. В случае заглавной буквы поле может принимать значение «NULL», в противном случае – нет. Значение длины ограничено диапазоном 0-254. Если оно равно нулю, то длина поля может быть переменной. Доступные типы:
В процессе инсталляции службой MS Installer выполняется некоторая последовательность операций. Это могут быть как встроенные операции – стандартные именованные процедуры, которые выполняет MS Installer, так и операции пользователя, определенные при создании инсталляции. Перечень выполняемых операций хранится в специальных таблицах. То, какие из этих таблиц будут использованы службой установки, зависит от значения свойства ACTION (INSTALL, ADMIN или ADVERTISE) и уровня пользовательского интерфейса. Эта зависимость представлена в таблице 5.
Название таблицы | Условия использования | |
---|---|---|
Тип инсталляции (значение свойства ACTION) | Уровень пользовательского интерфейса (значение свойства UILevel) | |
AdminExecuteSequence | ADMIN | Не важен |
AdminUISequence | ADMIN | Полный или сокращенный (5 или 4) |
AdvtUISequence | Таблица не используется. Должна либо отсутствовать в базе, либо не содержать записей. | |
AdvtExecuteSequence | ADVERTISE | Не важен |
InstallExecuteSequence | INSTALL | Не важен |
InstallUISequnce | INSTALL | Полный или сокращенный (5 или 4) |
Все перечисленные таблицы имеют одинаковую структуру и состоят из трех полей – наименование операции (Action), условия выполнения (Condition) и порядковый номер (Ordering).
Содержание поля «Condition» аналогично рассмотренным выше условиям установки компонента.
Поле «Ordering» предназначено для определения порядка выполнения перечисленных операций.
Поле «Action» может содержать имена как стандартных операций, так и определенных пользователем. Тема стандартных операций слишком объемна для журнальной статьи, поэтому здесь я приведу лишь ссылку на раздел MSDN, посвященный этому вопросу. Рассмотрим подробнее возможности, предоставляемые пакетом MakeMsi для формирования пользовательских операций.
Пользовательские операции (Custom action) предназначены для произвольного расширения функциональности msi-пакета. Для их описания предназначена таблица CustomAction, содержащая название операции (поле Action), ее тип (поле Type) и еще два поля (Source и Target), интерпретация значения которых зависит от значения поля Type.
Перечень возможных типов пользовательских операций и соответствующих значений полей таблицы CustomAction приведен в таблице 6.
Тип пользовательской операции | Значение поля «Type» | Значение поля «Source» | Значение поля «Target» |
---|---|---|---|
Вызов функции динамической библиотеки, содержащейся в бинарном потоке | 1 | Значение ключевого поля в таблице «Binary» | Точка входа в DLL |
Вызов функции динамической библиотеки, установленной в составе продукта | 17 | Значение ключевого поля в таблице «File» | Точка входа в DLL |
Выполнение EXE-файла, содержащегося в бинарном потоке | 2 | Значение ключевого поля в таблице «Binary» | Аргументы командной строки |
Выполнение EXE-файла, установленного в составе продукта | 18 | Значение ключевого поля в таблице «File» | Аргументы командной строки |
Отображение сообщения об ошибке и прекращение инсталляции | 19 | Пусто | Форматированное сообщение или значение ключевого поля в таблице «Error». |
Выполнение EXE-файла, путь которому указан в значении свойства | 50 | Значение ключевого поля в таблице «Property» | Аргументы командной строки |
Выполнение EXE-файла, расположенного в указанном каталоге | 34 | Значение ключевого поля в таблице «Directory» | Имя исполняемого файла. Дополнительно могут быть указаны аргументы командной строки. Длинные имена файлов должны быть заключены в кавычки. |
Выполнение Java-скрипта, содержащегося в бинарном потоке | 5 | Значение ключевого поля в таблице «Binary» | Необязательное указание вызываемой функции |
Выполнение Java-скрипта из файла, установленного в составе продукта | 21 | Значение ключевого поля в таблице «File» | Необязательное указание вызываемой функции |
Выполнение Java-скрипта, текст которого содержится в свойстве | 53 | Значение ключевого поля в таблице «Property» | Необязательное указание вызываемой функции |
Выполнение Java-скрипта | 37 | NULL | Код Jscript |
Выполнение VB-скрипта, содержащегося в бинарном потоке | 6 | Значение ключевого поля в таблице «Binary» | Необязательное указание вызываемой функции |
Выполнение VB-скрипта из файла, установленного в составе продукта | 22 | Значение ключевого поля в таблице «File» | Необязательное указание вызываемой функции |
Выполнение VB-скрипта, текст которого содержится в свойстве | 54 | Значение ключевого поля в таблице «Property» | Необязательное указание вызываемой функции |
Выполнение VB-скрипта | 38 | NULL | Код VBScript |
Установка значения свойства | 51 | Имя свойства или значение ключевого поля в таблице «Property» | Форматированная строка |
Сопоставление каталога из таблицы «Directory» с каталогом файловой системы | 35 | Значение ключевого поля в таблице «Directory» | Форматированная строка, представляющая абсолютное имя каталога файловой системы завершающим с обратным слешем |
Установка вложенного msi-пакета | 7 | Название хранилища, в котором находится устанавливаемый пакет | Значение свойств устанавливаемого пакета |
Установка msi-пакета, расположенного на том же носителе, что и запускающая инсталляция | 23 | Путь к msi-пакету | Значение свойств устанавливаемого пакета |
Запуск вложенной инсталляции для изменения состава или удаления установленного продукта | 39 | Код продукта (внутренний номер продукта в базе MSI Installer – GUID инсталляционного пакета) | Значение свойств устанавливаемого пакета |
Теги MakeMsi, предназначенные для создания пользовательских операций, аналогичны приведенным выше типам. Большинство из них имеют сходные параметры:
Type может принимать следующие значения:
<$DllCa> – предназначен для вызова функций динамической библиотеки. Функция должна иметь вполне определенный вид (по адресу http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcsample98/html/vcsmpcustact1.asp расположен пример реализации на C++). Пример использования:
;--- Включаем библиотеку в инсталляцию --- #( <$File RowKey="DllAsInstalledFile" SOURCE="C:\tst\Sample.dll" Destination="[INSTALLDIR]\TestDll.DLL" > #) ;--- Вызываем функцию TstFunc --------- #( <$DllCa File="DllAsInstalledFile" SEQ=5001 Entry="TstFunc" Condition="<$DLLCA_CONDITION_INSTALL_ONLY>" > #) ;--- Или используем бинарный поток ------ #( <$DllCa Binary="DllInBinaryTable" SEQ=2001 Entry="TstFunc" Condition="<$DLLCA_CONDITION_INSTALL_ONLY>" DLL=^C:\tst\Sample.dll^ > #) |
<$ExeCa> – предназначен для запуска исполняемого файла. Также может применяться к файлам из состава инсталляции и хранящимся в бинарных потоках:
<$Files "c:\tst\tst.exe"> <$/Component> ;--- Запускаем установленный файл ----------------------------------------- #( <$ExeCa EXE="[INSTALLDIR]tst.exe" Args=^[тут аргументы командной строки]^ CONDITION=^<$VBSCA_CONDITION_INSTALL_ONLY>^ Rc0="N" ;;Не проверяем код возврата Seq=4011 > #) ;--- Или запускаем его из бинарного потока -------------------------------- #( <$ExeCa Binary="tst.exe" EXE="c:\tst\tst.exe" CONDITION=^<$VBSCA_CONDITION_INSTALL_ONLY>^ Seq=4011 > #) |
<$JsCa> и <$VbsCa> предназначены для запуска Java- или VB-скриптов, помещенных в бинарный поток. Имеют дополнительный параметр DATA, указывающий на структуру, содержащую именованные переменные. В качестве иллюстрации использования этих тегов вернемся к примеру с использованием дополнительных потоков файлов. Применение этих тегов практически идентично, так что ограничимся одним примером. Реализуем на VBScript функцию, которая выполнит запись данных из таблицы FileStream в соответствующие файлы:
#data "Parameters" "DATABASE" "[DATABASE]" ;;Передаем имя устанавливаемого пакета "DestDir" "[INSTALLDIR]" ;;и каталог установки #data <$VbsCa Binary="WriteSecondStream.vbs" DATA="Parameters"> <$VbsCaEntry "Install"> const msiOpenDatabaseModeReadOnly = 0 dim streamView, fileView dim rec, rec1 dim stmt dim fl, fileName dim fs : set fs = CreateObject("Scripting.FileSystemObject") dim DB : DB = VbsCaCadGet("DATABASE") dim oDB : set oDB = session.installer.OpenDatabase(DB, _ msiOpenDatabaseModeReadOnly) if err.number <> 0 then on error goto 0 VbsCaRaiseError "WriteSecondStream()", "Ошибка открытия базы" & DB end if CaDebug 1, DB & " успешно открыта" set streamView = oDB.OpenView ("SELECT `File_`, `Info` FROM `FileStream`") if streamView is Nothing then on error goto 0 VbsCaRaiseError "WriteSecondStream()", "Ошибка открытия streamView" end if streamView.Execute CaDebug 1, "Открыт запрос потоков" set rec = streamView.Fetch while not (rec is Nothing) CaDebug 1, "Обрабатывается файл " & rec.StringData(1) stmt = "SELECT FileName FROM File WHERE File='" & _ rec.StringData(1) & "'" CaDebug 1, stmt set fileView = oDB.OpenView (stmt) if fileView is Nothing then on error goto 0 VbsCaRaiseError "WriteSecondStream()", "Ошибка открытия fileView" end if fileView.Execute CaDebug 1, "Открыт запрос списка устанавливаемых файлов" set rec1 = fileView.Fetch if not (rec1 is Nothing) then fileName = VbsCaCadGet("DestDir") & rec1.StringData(1) & _ ":SecStream" CaDebug 1, "Открытие файла " & fileName set fl = fs.OpenTextFile(fileName, 2, -1) CaDebug 1, "Запись данных " & rec.StringData(2) fl.Write rec.StringData(2) fl.Close end if fileView.Close set rec = streamView.Fetch wend streamView.Close set fs = Nothing set oDB = Nothing <$/VbsCaEntry> <$/VbsCa> #( <$VbsCaSetup Binary="WriteSecondStream.vbs" Entry="Install" Deferred="Y" Seq=4422 CONDITION=^<$CONDITION_INSTALL_ONLY>^ DATA="Parameters" > #) |
Глобальный объект «session» позволяет получить доступ к объектной модели службы MS Installer в контексте выполняемой сессии. Но при его использовании нужно иметь в виду, что к моменту выполнения отложенных операций (а в нашем примере именно так и есть – Deferred = "Y") значения свойств сессии становятся равны “NULL”. И если при Deferred = N мы можем получить каталог, в который производится установка, с помощью конструкции «session.property("INSTALLDIR")», то при выполнении отложенной операции придется передавать его через параметр «DATA», как показано в примере.
Тег <$VbsCa> используется совместно с тегом <$VbsCaEntry>, содержащим название функции, вызываемой при выполнении пользовательской операции, и <$VbsCaSetup>, предназначенным для задания условий выполнения и атрибутов операции.
При генерации скрипта MakeMsi создает некоторые вспомогательные функции, две из которых уже были использованы в примере. Это VbsCaRaiseError, генерирующая ошибку и прекращающая выполнение скрипта, и CaDebug, которая выводит содержимое своего второго параметра в качестве описания операции над индикатором выполнения (над первым или вторым, что определяется первым параметром) в диалоге ProgressDlg, и осуществляет запись в автоматически создаваемый (если не указано обратное) Log-файл. По умолчанию файлы протоколов пишутся в корень диска C, что бывает не всегда удобно. Для исправления этой ситуации служит макроопределение VBSCA_LOGDIR_ENVVAR, которому можно присвоить значение переменной окружения, содержащей имя каталога. Существует и другой способ – макроопределение VBSCA_LOGDIR_EXP_4_DEFAULT, в котором можно напрямую определить каталог для файлов протокола. Для отключения протоколирования выполнения скриптов можно воспользоваться макроопределением VBSCA_LOG_TO_FILE, установив его значение «N».
Еще одной вспомогательной функцией является CaMsgBox. Разработчик настоятельно рекомендует пользоваться ей вместо стандартной MsgBox, так как она проверяет уровень пользовательского интерфейса и не создает модального окна в том случае, когда это не требуется.
По этому адресу расположен сайт разработчика, Дениса Бариса, с которого можно скачать дистрибутив MakeMsi. На момент написания статьи последняя версия (04.267) находилась здесь Программа предоставляется бесплатно всем желающим с привычной маркировкой "as is". В состав дистрибутива входит достаточно полная документация в формате .chm и большое количество примеров. Кроме того, Денис Барис ведет новостную группу на Yahoo, где очень оперативно и доброжелательно отвечает на все задаваемые вопросы.
Помимо ресурсов, посвященных MakeMsi, определенный интерес представляют новостные группы Microsoft, посвященные вопросам службы инсталляции – microsoft.public.platformsdk.msi и microsoft.public.win2000.msi, очень информативный ресурс installsite.org и достаточно активный форум на myitforum.com.
Программа, написанная Денисом, позволяет создавать как простые, типовые инсталляции, так и сложные установочные пакеты. Во втором случае для использования всех предоставляемых программой возможностей требуются знания в области технологии MS Installer и скриптовых языков (VBScript или JavaScript). Автором проделан очень большой объем работы, который позволяет существенно ускорить процесс создания msi-пакетов, автоматизировав его основные операции. Помимо рассмотренного в статье примера создания нового инсталлятора, имеется возможность изменения существующей, сравнения двух пакетов с автоматической генерацией скрипта изменений (утилита DiffMsi), работы с merge-модулями и многое другое.
Проект имеет некоммерческий характер. Автор будет рад принять помощь в форме отчетов об ошибках, предложений по расширению функциональности и участия в форуме MakeMsi.
Сообщений 2 Оценка 155 Оценить |