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

    Для начала — что такое 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 — фрагменты и инклуды
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 29
    • +2
      Буду знать, спасибо. Почему-то я думал что такие вещи делаются без Visual Studio, каким-нибудь сторонним софтом :)
      • 0
        В данном случае Visual Studio используется всего лишь как оболочка.

        Создавать дистрибутивы с помощью WiX можно и, например, с помощью SharpDeveloper. Он, кстати, дает немного больше визуальности. Например, на стадии создания проекта можно выбрать набор UI. В нем есть встроенный редактор диалогов (в отличие от Visual Studio).
        • +2
          Да, не очень то удобно с VS. По мне лучше использовать InnoSetup, освоить его имхо легче)
        • +1
          Удобная штука, сами пользуемся. Из за того, что сам WiX проект инсталлятора идет в XML, он легко поддается автоматизации и сопровождению, удобно хранить в SVN. И сам инсталлер MSI довольно гибок. Первоначальная установка, сервис паки, автоматическое удаление.
          • +1
            Да, и для того что бы быстрее разобраться с виксом, можно воспользоватся программой WiXAware, она платная, но есть триал. Там через GUI можно подсмотреть многие заморочки WiX формата.
            • +1
              А есть опенсорсный аналог, тоже с возможностью визуального редактирования диалогов и логическим упорядочиванием всех сущностей WiX'а.
              К сожалению, в ней нет таких средств автоматизации типичных задач вроде регистрации ODBC, установки источников данных, как в WiXAware.

              wixedit.sourceforge.net/

              Небольшой комментарий по использованию:
              у программы есть багофича — программа ищет директорию с xsd-файлами WiX'а в папке C:\Program Files\Windows Installer XML v3\bin\doc — а в WiX они хранятся на одном уровне с папкой bin. Нужно просто скопировать папку doc вовнутрь bin.
            • 0
              Ну вот, ура товариши! наконец «все для разработчиков» :)
              • 0
                Вообще, я почему-то обычно не пишу благодарности в каментах, но это исключительный случай. Спасибо большое! :-)
                • +2
                  Спасибо за статью, достаточно подробно описан процесс.

                  Пользовался как-то WiX-ом. Он, конечно, придает гибкости по сравнению с простыми инсталяционными проектами в VS, но иногда его оказывается недостаточно. В итоге я остановился на NSIS (http://nsis.sourceforge.net/Main_Page).

                  Вот еще один полезный тул при создании инсталяционных пакетов: Orca.exe.
                  • –1
                    NSIS адже близко не стоял по функциональности к WiX (MSI), хотя и у него есть определенные преимущества — он проще в освоении.
                    • 0
                      И чего же Wix умеет такого волшебного?
                      • 0
                        например, что бы сертифицировать программу в майкрософт, она должна устанавливаться только с помощью MSI. а NSIS (да, проще и приятнее) с MSI не работает.
                        • 0
                          Товарищи, давайте не будем спорить о том, что лучше, а что хуже. Условия задачи опеределяют выбор инструмента. Лично сам я использую и NSIS и WiX.
                          • 0
                            Прошу прощенья за офтоп, а что дает данная сертификация?
                            • 0
                              она дает вам лэйбачок «Certified for» — www.windowsservercert.com/
                              иногда это очень помогает в продвижении продукта.
                              • 0
                                Да, увы порой это так. Для моего предыдущего начальника этой лейбочки хватило, для выбора ERP.
                                • 0
                                  да, путаница бывает.
                                  эта лейбочка говорит о том, что продукт прошел программу тестов на предмет корректной работы в ОС. но совсем не говорит о ее пригодности, качетсве, функциональности и проч.
                      • 0
                        Орка — это способ залезть ручкам в базу MSI, после этих изменений очень уж тяжело отлаживаться. Уже проходили. Лучше пользоваться более высокоуровневыми, например тем же виксом.
                        • 0
                          Orca может пригодится для создания трансформаций. О которых мы еще поговорим.
                          • +1
                            Пригодиться то она может, но зачем?
                            Для создания трансформаций есть готовые скрипты (их можно использовать из msbuild для автоматизации):
                            Windows Installer scripting Examples
                            msdn.microsoft.com/en-us/library/aa372865(VS.85).aspx
                      • 0
                        Не совсем понял один момент: какая версия windows installer должна стоят на клиенте, чтобы он мог работать с получившимся инсталлятором?
                        • 0
                          Версия указывается в ключе Package. В примере указана версия InstallerVersion=«200»
                      • –1
                        опять xml! ну, прям, жить без него не могут!
                        • 0
                          Консольный билдер у него есть?
                          Так чтоб ему подсунуть файл проекта, а он выдал готовый exe или ошибку.
                          • +1
                            Вот хорошая статья в эту тему:
                            Автоматизация создания версий с помощью MSBuild и Windows Installer XML (WiX)
                            msdn.microsoft.com/ru-ru/magazine/cc163456.aspx

                            Мы так и делали, запускали скрипт MSBuild для сборки сетапов.
                          • 0
                            Поработал в свое время с InstallShield. Приходилось много работать напильником — в том плане, что не всегда все дается стандартными средствами.
                            Расскажите в следующей статье как создать свой собственный диалог выбора файла =)
                            • 0
                              Спасибо! Хороший материал, а я давно уже большой поклонник WiX…
                              • 0
                                Спасибо большое. Статься очень помогла.

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.