На тьму надейся, а сам не плошай

Для продукта, над которым я сейчас работаю, нужно было сделать инсталляцию под Windows. Установить несколько файлов, создать пару ключей в реестре, обновиться на более свежую версию,.. - как раз работа для WiX. WiX, - он, конечно, не без греха. Все-таки, это всего лишь обертка вокруг Windows Installer, чьё нетривиальное нутро то и дело дает о себе знать. Взять хотя-бы тот факт, что Windows Installer понимает черытех компонентный номер версии (a.b.c.d), но при сравнии номеров версий принимает во внимание только старшие три числа.

Так или иначе, инсталляция вскоре была готова и встал вопрос как её подписывать. Для подписи нужен ключ, который живет на отдельной сборочной машине, запертой, дабы уменьшить риск утечек, в датацентре за семью замками. А датацентр - в утке, а утка в зайце… Инсталлация и бинарники собираются как часть официальной сборки Chrome. Подписывать нужно как сами бинарники, так и файл инсталляции (.MSI). Родилась идея - на машину с ключем копируется только готовый .MSI. Там он распаковывается, бинарники подписываются, инсталация перепаковывается и подписывается. Красота и гармония.

Плохая, негодная была идея, как оказалось. Нет, поначалу все работало как часы. Более того, во время каждой сборки Chrome прогонялся тест, который проверял, что только что собранная исталляция может быть распакована и успешно запакована назад. Но потом вдруг сломались обновления. Неподписанные инсталляции ставились поверх старых версий безо всяких проблем. А подписанные - ни в какую. Выяснилось, что утилита DARK.EXE из состава WiX, которую мы использовали для распаковки .MSI, переставляла действие RemoveExistingProducts после InstallFinalize, несмотря на то, что исходный скрипт указывал, что это действие должно выполнятся после InstallInitialize. В результате старая версия продукта удалялась уже после установки новой версии, удаляя только что созданные ключи в реестре.

Этот баг удалось обойти расписав элемент MajorUpgrade как комбинацию из элементов Upgrade, Condition и RemoveExistingProducts. Но затем обновления сломались еще раз. Теперь уже потому, что DARK.EXE терял атрибут IncludeMinimum=”no” в элементе UpgradeVersion, что ломало логику сравнения версий во время обновления. Стало ясно, что простой как палка, рабоче-крестьянский способ “запаковать все нужные файлы в .ZIP” работал бы как часы. Последний гвоздь в гроб отличной идеи “обойтись одним .MSI” забило то, что после обновления версии WiX до 3.6, инсталляция, распакованная DARK.EXE вообще отказалась повторно собираться.

comments powered by Disqus