среда, 17 декабря 2014 г.

Создание инсталлятора с помощью WiX. Часть 3. Обновление

Привет! Наконец удалось найти время для продолжения серии заметок про написание инсталляторов. В прошлых статьях мы рассмотрели создание простого инсталлятора,  который умеет принимать от пользователя номер порта, на котором будет работать устанавливаемая служба.


В этой статье я хочу рассмотреть процесс обновления программного обеспечения. Сейчас нам для обновления нашей службы необходимо удалить предыдущую версию и установить новую. Если попробовать установить новую версию поверх старой, то старая версия удалена не будет. В системе останутся записи об обеих версиях, даже если мы установим их в одно место. Останется два комплекта ярлыков и два пункта с наименованием программы в элементе панели управления «Программы и компоненты». Такой режим ручного удаления и установки нам явно не очень удобен, и его необходимо автоматизировать.

WiX позволяет создавать три типа обновлений:
  1. Major upgrade – самый простой тип обновлений, это обычный MSI инсталлятор, как мы создавали раньше. Отличие только в том, что если он обнаружит предыдущую версию продукта, то он ее удалит. То есть предыдущая установленная версия будет удалена, а новая будет установлена на чистое место. Данный подход требует изменения версии и кода продукта (об этом ниже).
  2. Minor upgrade обновляет существующие файлы без деинсталляции установленного продукта. Этот режим можно использовать для исправления дефектов или поставки новых фич и компонентов.
  3. Small update обычно поставляется в виде патча, в нем меньше по объему изменений чем minor upgrade.
Я не хочу приводить полный список различий этих трех типов обновлений. Вместо этого я сфокусируюсь на подготовке major upgrade, так как этот подход самый простой в реализации и самый, по-моему, понятный способ обновлений.

Итак, major upgrade – это полный инсталляционный пакет, который удаляет более старую версию продукта и устанавливает новую. Чтобы его создать, нужно выполнить следующие действия:
  • В секции Product изменить значение элемента Id на новый Guid.
  • Увеличить значение версии продукта (элемент Version в секции Product).
  • Добавить и сконфигурировать секцию MajorUpgrade.
Далее подробно рассмотрим все три пункта.

В качестве нового идентификатора продукта в элемент Id можно каждый раз подставлять новый Guid, но проще и удобней будет использовать значение * (звездочка). Это будет означать, что WiX будет сам подставлять новый идентификатор при каждой компиляции проекта.

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

Теперь секция Product будет выглядеть так:
<Product Id="*" 
    Name="$(var.ProductName)" 
    Language="1049" 
    Version="$(var.Version)" 
    Manufacturer="$(var.Manufacturer)" 
    UpgradeCode="ceed7874-addb-4b86-af85-e6feb748b6c1">

Стоит отметить, что по сравнению с предыдущей версией тут был проведен небольшой рефакторинг: значения, которые могут измениться, были вынесены в переменные, и обращение к ним происходит по наименованиям. Для этого я создал в проекте файл Variables.wxi и перенес туда все значения, которые могут измениться. Файл выглядит так:
<?xml version="1.0" encoding="utf-8"?>
<Include>
  <?define Version="1.0.1.0"?>
  
  <?define DefaultPort="8888"?>

  <?define ProductName="ApplicationInstaller"?>
  <?define Manufacturer="MySoftInc"?>

  <?define InstallLocation="ApplicationServer"?>
</Include>

Далее я подключил этот файл к файлу Product.wxs  с помощью директивы <?include Variables.wxi?>  и заменил значения на наименования переменных. Имя переменной выглядит так $(var.Version), где после var. идет собственно наименование переменной.

Последним этапом осталось настроить секцию MajorUpgrade. Если этого не сделать, то при установке новой версии старая не будет удалена. И их обе можно будет увидеть в элементе панели управления «Программы и компоненты». Добавим в файл Product.wxs следующую секцию перед описанием директорий установки.
<MajorUpgrade 
   DowngradeErrorMessage="Более новая версия [ProductName] уже установлена." 
   Schedule="afterInstallExecute"/>

При попытке установить более старую версию поверх новой будет выведено сообщение «Более новая версия ApplicationInstaller уже установлена», и установка будет прекращена. Значение элемента Schedule говорит о том, что сначала будет установлена новая версия, и только потом будет удалена старая. Если по какой-то причине возникнет сбой при установке, то установка откатится до предыдущей версии.

Теперь инсталлятор готов и умеет сам себя обновлять. Исходники примера можно взять здесь (папка WixExample3).

Комментариев нет:

Отправить комментарий