Pull to refresh

Создание инсталлятора с помощью WiX

Reading time 9 min
Views 102K
Для начала — что такое WiX? Технология WiX (Windows Installer XML) представляет собой набор инструментов и спецификаций упрощающих процесс создания дистрибутивов на базе MSI (Microsoft Installer). Если объяснять проще то это обертка вокруг MSI с человеческим лицом.

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


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

Приветствие



Лицензионное соглашение



Выбор директории



Начало установки



Для создания дистрибутива нам понадобится сам WiX, последнюю версию которого всегда можно скачать на Source Forge. На данный момент последняя версия 3.5.0828.0.

Необходимо скачать и установить:
1. ProjectAggregator2.msi — нужен, для того, чтобы установить Votive (находится внутри дистрибутива номер 2). Который, в свою очередь, является дополнением для Visual Studio, облегчающим процесс работы с WiX (подсветка синтаксиса, IntelliSense).
2. Wix35.msi или Wix35_x64.msi (в зависимости от платформы)
3. Русский языковой файл

Итак, скачали, установили, запускаем Visual Studio. Меню File -> New Project, если все установлено правильно — появился новый раздел Windows Installer XML. Выбираем шаблон проекта Setup Project, вводим название проекта (я оставил как есть SetupProject1).



Проект будет состоять из одного файла Product.wxs с ним мы и будем работать. В моем случае файл выглядел следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product Id="b7bc7c6f-9a4e-4973-be84-eca8e3427c97" Name="SetupProject1" Language="1033" Version="1.0.0.0" Manufacturer="SetupProject1" UpgradeCode="06a81104-1e30-463d-87e1-e8a79b4c682a">
    <Package InstallerVersion="200" Compressed="yes" />

    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLLOCATION" Name="SetupProject1">
          <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
          <!-- <Component Id="ProductComponent" Guid="b11556a2-e066-4393-af5c-9c9210187eb2"> -->
            <!-- TODO: Insert files, registry keys, and other resources here. -->
          <!-- </Component> -->
        </Directory>
      </Directory>
    </Directory>

    <Feature Id="ProductFeature" Title="SetupProject1" Level="1">
      <!-- TODO: Remove the comments around this ComponentRef element and the Component above in order to add resources to this installer. -->
      <!-- <ComponentRef Id="ProductComponent" /> -->
    </Feature>
  </Product>
</Wix>


* This source code was highlighted with Source Code Highlighter.


Для начала настроим внешний вид и добавим поддержку русского языка.

Начнем с добавления русского языка. Для этого:
1. В ключе Product изменяем 1033 на 1049
2. В свойствах проекта (правой клавишей по названию проекта в Solution Explorer -> Properties), закладка Build, в поле Cultures to build вставляем ru-RU
3. Добавляем к проекту (правой клавишей по названию проекта в Solution Explorer -> Add -> Existing Item) файл WixUI_ru-ru.wxl (из архива WixUI_ru-ru.v3.zip)

В сгенерированном проекте нет ни одного диалогового окна. Существуют два варинта добавления диалоговых окон — создавать самостоятельно, либо воспользоваться готовым набором диалоговых окон.

Мы пойдем вторым путем, начинать знакомство лучше с простого. Для этого необходимо добавить ссылку на WixUIExtension.dll (правой клавишей по названию проекта в Solution Explorer -> Add Reference — открываем папку, в которую был установлен WiX, подкаталог bin)

Ссылку добавили, указываем какой набор мы будем использовать, в конце раздела Product добавим

<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" ></Property>
<WixVariable Id="WixUILicenseRtf" Overridable="yes" Value="License.rtf"/>
<UIRef Id="WixUI_InstallDir"/>


* This source code was highlighted with Source Code Highlighter.


WixVariable Id=«WixUILicenseRtf» — указывает на путь к файлу лицензии (речи о нем пока не шло, добавили сразу, чтобы два раза не ходить).
WixUI_InstallDir — готовый набор диалоговых окон. Данный набор включает все необходимые нам диалоги. Помимо него так же существуют наборы WixUI_Advanced, WixUI_Mondo, WixUI_FeatureTree, WixUI_InstallDir, WixUI_Minimal.

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

Ключ Product — описывает свойства продукта.
Id — идентификатор продукта, уникальный GUID.
Name — название продукта
Language — язык пакета установки
Version — версия продукта
Manufacturer — производитель
UpgradeCode — уникальный GUID

Чтобы упростить себе жизнь определим некоторые переменные. Для чего — название продукта, например, не раз может встречаться в скрипте, если нам захочется его изменить придется искать его по всему скрипту и менять на новое. Чтобы избежать этого определим переменную, которая будет содержать название продукта и, в случае необходимости, будем менять только ее. Над разделом Product добавим:

<?define ProductName="SetupProject1" ?>
<?define ProductVersion="1.0.0.0" ?>
<?define ProductCode="b7bc7c6f-9a4e-4973-be84-eca8e3427c97"?>
<?define UpgradeCode="06a81104-1e30-463d-87e1-e8a79b4c682a"?>
<?define Manufacturer="MyCompany"?>


* This source code was highlighted with Source Code Highlighter.


Теперь заменим значение параметров ключа Product на переменные:

<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1049" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">

* This source code was highlighted with Source Code Highlighter.


Определимся теперь с тем куда мы будем устанавливать наш продукт.

Ключ Directory — определяет путь для установки.
Directory Id=«TARGETDIR» корневой элемент для всех папок, которые будут использоваться для установки проекта.
Directory Id=«ProgramFilesFolder» папка Program Files (на что указывает Id=«ProgramFilesFolder»).
Directory Id=«INSTALLLOCATION» папка с именем SetupProject1 в папке Program Files. Заменим сразу Name=«SetupProject1» на Name="$(var.ProductName)"

Добавим файлы в пакет установки. Для этого сначала добавим устанавливаемые компоненты. Следуя совету «Remove the comments around this Component» уберем комментарии с Component внутри целевой папки и добавим туда, например, калькулятор.

<Component Id="ProductComponent" Guid="b11556a2-e066-4393-af5c-9c9210187eb2">
  <File Id='Calc' DiskId='1' Source='C:\WINDOWS\system32\calc.exe'/>
</Component>


* This source code was highlighted with Source Code Highlighter.


Установка компонента невозможна без включения его в одну из Feature (если честно не уверен как в данном случае можно перевести этот термин на русский язык). Этот элемент может быть использован когда нам необходимо дать пользователю возможность выбора, что устанавливать, а что нет. В условиях нашей задачи ничего не говорилось о возможности выбора, но несмотря на это нам необходимо привязать описанный Component к одной единственной Feature:

<Feature Id="ProductFeature" Title="$(var.ProductName)" Level="1">
  <ComponentRef Id="ProductComponent" />
</Feature>


* This source code was highlighted with Source Code Highlighter.


Осталось добавить ярлык в меню Пуск.

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

В раздел Directory Id=«TARGETDIR», где-нибудь в конце добавляем:

<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="$(var.ProductName)">
 <Component Id="ApplicationShortcutCalc" Guid="4CEBD68F-E933-47f9-B02C-A4FC69FDB551">
  <Shortcut Id="ShortcutCalc"
       Name="Calc"
       Description="$(var.ProductName)"
       Target="[INSTALLLOCATION]Calc.exe"
       WorkingDirectory="INSTALLLOCATION"/>
  <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
  <RegistryValue Root="HKCU" Key="Software\$(var.Manufacturer)\$(var.ProductName)" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
 </Component>
</Directory>
</Directory>


* This source code was highlighted with Source Code Highlighter.


Начинаем разбираться:
Directory Id=«ProgramMenuFolder» — указывает на директорию, в которой содержатся ярлыки меню Пуск.
Directory Id=«ApplicationProgramsFolder» — папка нашей программы в меню Пуск
Component — компонент, содержащий ярлык (не забыть включить его в Feature)
Shortcut — собственно ярлык к калькулятору

Финальная версия файла должна выглядеть так:

<?xml version="1.0" encoding="UTF-8"?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
 <?define ProductName="SetupProject1" ?>
 <?define ProductVersion="1.0.0.0" ?>
 <?define ProductCode="b7bc7c6f-9a4e-4973-be84-eca8e3427c97"?>
 <?define UpgradeCode="06a81104-1e30-463d-87e1-e8a79b4c682a"?>
 <?define Manufacturer="MyCompany"?>

 <Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1049" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
    <Package InstallerVersion="200" Compressed="yes" />

    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLLOCATION" Name="$(var.ProductName)">
          <Component Id="ProductComponent" Guid="b11556a2-e066-4393-af5c-9c9210187eb2">
      <File Id='Calc' DiskId='1' Source='C:\WINDOWS\system32\calc.exe'/>
          </Component>
        </Directory>
      </Directory>
   <Directory Id="ProgramMenuFolder">
    <Directory Id="ApplicationProgramsFolder" Name="$(var.ProductName)">
     <Component Id="ApplicationShortcutCalc" Guid="4CEBD68F-E933-47f9-B02C-A4FC69FDB551">
      <Shortcut Id="ShortcutCalc"
           Name="Calc"
           Description="$(var.ProductName)"
           Target="[INSTALLLOCATION]Calc.exe"
           WorkingDirectory="INSTALLLOCATION"/>
      <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
      <RegistryValue Root="HKCU" Key="Software\$(var.Manufacturer)\$(var.ProductName)" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
     </Component>
    </Directory>
   </Directory>
    </Directory>

    <Feature Id="ProductFeature" Title="SetupProject1" Level="1">
   <ComponentRef Id="ProductComponent" />
   <ComponentRef Id="ApplicationShortcutCalc" />
  </Feature>

  <Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" ></Property>
  <WixVariable Id="WixUILicenseRtf" Overridable="yes" Value="License.rtf"/>
  <UIRef Id="WixUI_InstallDir"/>
  
  </Product>
</Wix>


* This source code was highlighted with Source Code Highlighter.


Делаем Build, запускаем, проверяем результат.

Где еще почитать
Страница проекта
Alex Shevchuk: From MSI to WiX (в основном на английском, но есть немного на русском)
WiX Tutorial
wixwiki

Продолжение Часть 2 — фрагменты и инклуды
Tags:
Hubs:
+33
Comments 29
Comments Comments 29

Articles