» Создание своего инсталлятора на NSIS. Первые шаги

K.A.V.
www.oszone.net
22.02.2010
Автор: hb860
Последнее обновление: 22.02.2010

NSIS,или Nullsoft Script Installer System - это система создания инсталляторов для Microsoft Windows с открытыми исходными кодами, созданная компанией Nullsoft, основанной создателями Winamp. NSIS создан как альтернатива InstallShield, предназначенного для коммерческих продуктов.

Инсталляторы, созданные при помощи NSIS, отличаются высокой степенью сжатия исходного набора файлов и малым размером выходного дистрибутива.

В планах нашего проекта создать цикл статей, посвященных этому продукту.

Итак, инсталлятор на NSIS представляет собой файл скрипта, в котором каждая строчка — это отдельная команда, строчка, начинающаяся с «;» - это комментарий . Для написания этого скрипта достаточно обычного блокнота, однако я рекомендую использовать «необычный», с подсветкой синтаксиса, например, этот: http://notepad-plus.sf.net/ или этот http://hmne.sourceforge.net/.
Я использую первый вариант, Notepad++.

NSIS позволяет задать, как будет выглядеть скомпилированный инсталлятор. Реализовано это подключением модуля интерфейса. По умолчанию в состав системы входит три модуля интерфейса пользователя - Default User Interface (Интерфейс по умолчанию), Modern User Interface (Современный интерфейс) и Tiny User Interface (Облегченный интерфейс).

Наиболее распространены Default и Modern (на рисунках соответственно):




Для простоты освоения, мы будем работать с Modern UI (а кроме того, автору публикации он нравится больше всего).

Файл скрипта NSIS – это обычный текстовый файл с расширением NSI. Создаем новый файл, к примеру, MyScript.nsi

Для начала наметим общий подход к созданию инсталлятора. Для удобства разработки мы создадим некое подобие шаблона и будем использовать его в каждом из скриптов. Для этого зададим перечень констант. Константа в NSIS задается командой !define. Пример:

!define SOME_CONSTANT "SomeApp"


SOME_CONSTANT – имя константы, "SomeApp" — её значение.

Определим следующие константы:
;имя приложения
!define PRODUCT_NAME "Название приложения"
;версия приложения
!define PRODUCT_VERSION "1.0"
;папка, где будут храниться исходные файлы, подлежащие сжатию.
!define pkgdir "d:\package"


Поподробней про последнюю константу. Она служит для указания корневой папки, в которой будут лежать файлы проекта, подлежащие включению в дистрибутив. Это полезно для тех случаев, когда эта папка у вас участвует в нескольких участка кода скрипта, и в случае, если вы переместили исходный набор в другую папку, придется поправить путь только в одном месте. Очень практично.

После того, как мы определили нужные нам константы, подключаем библиотеку «современного» интерфейса пользователя:

!include "MUI.nsh"


Команда !include позволяет включить в тело скрипта файл, который трактуется компилятором так, как будто бы он является текстом скрипта. Предположим, есть такой код

!define Const1 “a”
!include “somefile.nsh”
!define Const2 “b”


Пусть файл “somefile.nsh” состоит только из одной строки: !define ConstFormFile “z”, тогда для компилятора скрипт будет выглядеть так:

!define Const1 “a”
!define ConstFormFile “z”
!define Const2 “b”


Чтобы вести разговор не на пустом месте, рассмотрим создание простейшего инсталлятора для браузера Opera. Решать он будет следующие задачи:



Подобный дистрибутив будет иметь также и практическую пользу для людей, часто производящих массовую установку приложений, например, системным администраторам, позволяя установить браузер без участия пользователя.

Итак, как мы уже условились, определяем константы и подключаем модуль интерфейса.

Следующее, что нам необходимо сделать, это задать степень сжатия исходных файлов. Делается это командой SetCompressor. NSIS поддерживает несколько методов: ZLIB, BZIP2 и LZMA. Не вдаваясь в технические подробности, скажем, что наиболее оптимальным методом сжатия является именно LZMA, обеспечивающий быструю скорость распаковки и высокий уровень сжатия. Вы можете указать команде опцию /SOLID, указывающую компилятору поместить все сжимаемые данные в один блок, тем самым дополнительно увеличив степень сжатия фалов инсталлятора.

SetCompressor /SOLID lzma


Так как «современный» интерфейс мы подключили, самое время заняться его настройкой. Настраивается он путем задания значений констант уже знакомой нам командой !define.

Константа MUI_ABORTWARNING определяет, выдавать ли предупреждение при закрытии инсталятора пользователем. По типу такого: «Вы действительно хотите прервать установку ..бла бла » и кнопки «да» и «нет».

!define MUI_ABORTWARNING


Константа MUI_ICON определяет значок инсталятора:

!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"


Здесь ${NSISDIR} - системная константа, означает путь к папке, куда установлен сам NSIS.
Предопределенных констант несколько:

$PROGRAMFILES, $PROGRAMFILES32, $PROGRAMFILES64 — папка Program files. В 64разрядной системе констатация $PROGRAMFILES и $PROGRAMFILES32 представляют папку C:\Program Files (x86), а $PROGRAMFILES64 - C:\Program Files.

$COMMONFILES, $COMMONFILES32, $COMMONFILES64 — по аналогии с предыдущей константой, ссылается на C:\Program Files\Common Files.

$DESKTOP — Папка рабочего стола. В современных операционных системах рабочий стол может быть общим (для всех пользователей) или персональным. По умолчанию константа ссылается на персональный рабочий стол текущего пользователя, но её значение можно переопределить командой SetShellVarContext. SetShellVarContext all – папка будет представлять общий рабочий стол, SetShellVarContext current – текущий.

$EXEDIR — папка, откуда запущен инсталятор.

$EXEFILE — имя исполняемого файла инсталятора.

$EXEPATH — полный путь инсталятора, т.е. $EXEDIR+$EXEFILE

$WINDIR — папка, куда установлена операционная система. Как правило, C:\Windows.

$SYSDIR — системная директория Windows. Обычно это C:\Windows\System32.

$TEMP — папка для временных файлов. Например, C:\Windows\Temp

$STARTMENU — папка меню «пуск». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$SMPROGRAMS – папка «Меню пуск-Программы». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$SMSTARTUP — Папка в меню пуск с названием «Автозагрузка». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$QUICKLAUNCH — Папка панели «Быстрый запуск». Если такой папки в системе нет — возвращается путь, равный $TEMP.

$DOCUMENTS — Папка «Мои документы». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$SENDTO — Папка «Отправить» контекстого меня проводника.

$RECENT — Папка с ярлыками «Недавние документы». Она присутствует в меню пуск

$FAVORITES — Папка «Избранное». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$MUSIC — Папка «Мои Документы\Моя музыка». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$PICTURES — Папка «Мои Документы\Мои рисунки». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$VIDEOS — Папка «Мои Документы\Видео». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$NETHOOD — Папка с ярлыками на сетевые объекты «Сетевое окружение»

$FONTS — Системная папка со шрифтами (C:\Windows\Fonts).

$TEMPLATES — Системная папка с шаблонами документов. Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$APPDATA — папка с данными учётной записи пользователя (c:\Documents and Settings\Ваше имя\Application Data\ или c:\Documents and Settings\All Users\Application Data\). Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$LOCALAPPDATA – папка c:\Documents and Settings\Ваше имя\Local Settings\Application Data\. Аналогично предыдущей.

$PRINTHOOD — ссылка на папку «Принтеры»

$INTERNET_CACHE — папка с временными файлами приложения Internet Explorer.

$COOKIES — Папка, содержащая файлы-cookies Internet Explorer.

$HISTORY — история посещений Internet Explorer.

$PROFILE — папка, где хранится системный профиль пользователя, например, C:\Documents and Settings\Foo.

$ADMINTOOLS — Папка «Администрирование». Для неё справедливо замечание SetShellVarContext, равно как и для $DESKTOP.

$RESOURCES — Ссылка на папку C:\windows\resources.

$RESOURCES_LOCALIZED — Ссылка на папку локализованных ресурсов Widnows, например, C:\Windows\Resources\1033.

$CDBURN_AREA — папка, где хранятся файлы, ожидающие записи на компакт-диск средствами Windows.

$HWNDPARENT – цифровой идентификатор родительского окна.

$PLUGINSDIR — папка, где хранятся плагины NSIS.

Обратите внимание, что под разными версиями Windows определенные константы могут быть недоступны. В Windows 98, к примеру, нет $CDBURN_AREA.

В строковых ресурсах скрипта системные константы используются именно в том виде, в котором приведены выше, к примеру:

DetailPrint 'Плагины NSIS тут: $PLUGINSDIR'


Для констант, определенных пользователем, синтаксис другой:
DetailPrint 'Программа ${PRODUCT_NAME}'


Далее необходимо определиться со страницами, которые будут видны конечному пользователю.
Они определяются через вызов макросов - логически завершенных блоков кода, определенных, как несложно догадаться, в файле MUI.nsh.

В данном примере нам потребуются


Соответственно, необходимо вставить следующие строки в наш скрипт:

!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH


Если мы хотим, чтобы все страницы нашего скрипта были на русском языке, необходимо также добавить вызов макроса локализации:

!insertmacro MUI_LANGUAGE "Russian"


Запущенный инсталлятор должен иметь заголовок, отражающий его назначение, такой как, например, «Установка Microsoft Office». Этого можно добиться, используя две следующих инструкции:



Имя файла инсталлятора задается командой OutFile. Вот так:

OutFile "${PRODUCT_NAME}-${PRODUCT_VERSION}.exe"


Получится Opera-10.10.exe

Следующая команда, ShowInstDetails, говорит компилятору, что в окне хода выполнения инсталлятора должен быть виден протокол его действий. По умолчанию он скрыт, и появляется только по нажатию кнопки «Детали». Возможные значения: hide, show и nevershow. Значению по умолчанию соответствует hide, nevershow отключает и вышеупомянутую кнопку, а мы используем show — показывать.

ShowInstDetails show


На этом в нашем конкретном примере мы закончим определять настройки нашего инсталлятора, и перейдем к самой важной логической составляющей любого инсталлятора на языке NSISсекции.

Секции — это логический блок команд, наличие которого является обязательным. Инсталлятор должен содержать хотя бы одну секцию. Именно в секциях производятся действия над файлами, операции с реестром, ярлыками и файловой системой.
Блок команд, входящих в секцию, обрамляется ключевыми словами Section- SectionEnd. Мы поговорим о секциях более подробно позднее, сейчас же нам необходимо создать главную секцию для нашего скрипта. Дополняем наш скрипт следующими строчками:

Section
SetOutPath "$TEMP"


Команда SetOutPath указывает компилятору, куда производить распаковку файлов. В нашем варианте мы для распаковки файлов используем временную папку системы.


А вот какие файлы подлежат распаковке, определяет команда File:

File"${pkgdir}\opera\1049.MST"
File"${pkgdir}\opera\opera installer.msi"


Стоп, спросите вы, а откуда взялись эта два файла ? Чтобы получить их, нам необходимо запустить «родной» инсталлятор браузера Opera Opera_1010_int_Setup.exe. Дожидаемся окна выбора языка

Выбираем русский язык, жмем ОК и ждем следующее окно.

Во временной папке (Введите в «Пуск-Выполнить» %TEMP% и нажмите Enter) найдите файл Opera installer.msi. Рядом с ним вы обнаружите и файл 1049.MST. Родной инсталлятор можно закрыть.

Помещаем два этих файла в папку исходных файлов для инсталлятора, в нашем случае это

${pkgdir}\opera\=D:\package\opera


Вернемся к скрипту. Файлы мы распаковали во временную папку, теперь надо бы установить оттуда браузер. Сделаем это так:

ExecWait "msiexec.exe /i $\"$TEMP\opera installer.msi$\" /qb ALLUSERS=1 CREATE_DESKTOP_ICON=1 CREATE_QUICKLAUNCH_ICON=1 CREATE_STARTMENU_ICONS=1 MULTI_USER_SETTING=1 TRANSFORMS=$\"$TEMP\1049.MST$\"" 


Команда ExecWait запускает внешнюю программу и ждет, когда она отработает. В данном случае мы запускаем Windows Installer для установки пакета opera installer.msi с параметрами:

ALLUSERS=1 — для всех пользователей

CREATE_DESKTOP_ICON=1 — создать иконку на рабочем столе

CREATE_QUICKLAUNCH_ICON=1 — создать иконку в панели быстрого запуска

CREATE_STARTMENU_ICONS=1 — создавать ярлыки в меню «Пуск»

MULTI_USER_SETTING=1 — использовать отдельный профиль для каждого пользователя системы

TRANSFORMS=... — подключаем файл параметров пакета MSI

После того, как браузер установился, мы можем смело стереть эти файлы:

Delete "$TEMP\opera installer.msi"
Delete "$TEMP\1049.MST"


Включим в дистрибутив компонент flash-плеер, чтобы не пришлось его ставить отдельно. Процедура аналогична предыдущей:

File"${pkgdir}\opera\install_flash_player.exe"
ExecWait "$TEMP\install_flash_player.exe /S"
Delete "$TEMP\install_flash_player.exe"


Теперь включим в инсталлятор дополнительные обложки пользовательского интерфейса.

SetOutPath "$PROGRAMFILES\Opera\Skin"
File"${pkgdir}\opera\*.zip"


В данном блоке кода мы меняем путь для распаковки на Program Files\Opera, и включаем все файлы с расширением ZIP в наш дистрибутив. К слову, команда File умеет не только включать, но и исключать файлы. Пример:

File /r /x *.arj c:\nsis\*.*


Не включать файлы с расширением *.arj, но включить все остальные файлы из папки c:\nsis и всех вложенных в неё папок.

Закрываем секцию командой SectionEnd. Скрипт готов. У нас должно было получиться что то подобное:

!define PRODUCT_NAME "Opera"
!define PRODUCT_VERSION "10.10"
!define pkgdir "d:\package"

!include "MUI.nsh"
SetCompressor /SOLID lzma

!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "Russian"

Name "${PRODUCT_NAME}"
Caption "Установка ${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "${PRODUCT_NAME}-${PRODUCT_VERSION}.exe"
ShowInstDetails show

Section
SetOutPath "$TEMP"
File"${pkgdir}\opera\1049.MST"
File"${pkgdir}\opera\opera installer.msi"
ExecWait "msiexec.exe /i $\"$TEMP\opera installer.msi$\" /qb ALLUSERS=1 CREATE_DESKTOP_ICON=1 CREATE_QUICKLAUNCH_ICON=1 CREATE_STARTMENU_ICONS=1 MULTI_USER_SETTING=1 TRANSFORMS=$\"$TEMP\1049.MST$\"" 
Delete "$TEMP\opera installer.msi"
Delete "$TEMP\1049.MST"

File"${pkgdir}\opera\install_flash_player.exe"
ExecWait "$TEMP\install_flash_player.exe /S"
Delete "$TEMP\install_flash_player.exe"

SetOutPath "$PROGRAMFILES\opera\Skin"
File"${pkgdir}\opera\*.zip"
SectionEnd


Если запустить Opera-10.10.exe c ключом /S (буква долна быть именно БОЛЬШАЯ), то вы не увидите никаких окон инсталлятора NSIS (правда, увидите окна Windows Installer, но я и не ставил целью их спрятать), и установка пройдет автоматически и без лишних вопросов.