Як здійснити оновлення програми встановлення WiX?


233

На роботі ми використовуємо WiX для створення інсталяційних пакетів. Ми хочемо, щоб установка продукту X призвела до видалення попередньої версії цього продукту на цій машині.

Я читав в кількох місцях в Інтернеті про велике оновлення, але не зміг його працювати. Чи може хто-небудь, будь ласка, вказати точні кроки, які мені потрібно зробити, щоб додати функцію видалення попередньої версії до WiX?

Відповіді:


189

У новіших версіях (від бета-версії 3.5.1315.0) ви можете використовувати елемент MajorUpgrade замість власного.

Наприклад, ми використовуємо цей код для автоматичного оновлення. Це запобігає пониженню рівня, надаючи локалізоване повідомлення про помилку, а також запобігає модернізації вже існуючої ідентичної версії (тобто оновлені лише нижчі версії):

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />

8
Про це в блозі Боба Арнсона надається багато приємної інформації.
Дейв Андерсен

17
Примітка: ніде не задокументовано, але <MajorUpgrade>елемент " " повинен бути розміщений після <Package> . В іншому випадку candleвидається така помилка: "помилка CNDL0107: Не вдалося перевірити схему із наступною помилкою у рядку 1, стовпець 473: Елемент" Продукт "у просторі імен" schemas.microsoft.com/wix/2006/wi "має недійсний дочірній елемент" MajorUpgrade 'в просторі імен' schemas.microsoft.com/wix/2006/wi 'Список можливих очікуваних елементів:' Пакет '. "."
Роб Ш

21
+1 Ця відповідь повинна отримати якомога більше оновлень; Дуже спокусливо піти з відповіддю, що має 5 разів вище, але використовує більш старі підходи.
Лінн Кришиться

1
Гарна думка. Я додав приклад, щоб люди не ігнорували його лише тому, що його немає!
Мураха

6
Відразу хочу відзначити, що вам не потрібно вказувати AllowDowngradesабо AllowSameVersionUpgrades. Вони за замовчуванням вже немає.
Світлий

221

Нарешті я знайшов рішення - розміщую його тут для інших людей, які можуть мати ту саму проблему (усіх 5):

  • Змініть ідентифікатор продукту на *
  • До продукту додайте наступне:

    <Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
    <Upgrade Id="YOUR_GUID">  
       <UpgradeVersion
          Minimum="1.0.0.0" Maximum="99.0.0.0"
          Property="PREVIOUSVERSIONSINSTALLED"
          IncludeMinimum="yes" IncludeMaximum="no" />
    </Upgrade> 
  • У розділі InstallExecuteSequence додайте:

    <RemoveExistingProducts Before="InstallInitialize" /> 

Відтепер, коли я встановлюю продукт, він видаляв попередні встановлені версії.

Примітка: замініть Id оновлення власним GUID


153
так, вивчати WiX - це як намагатися з'ясувати незрозумілі заклики, які хтось вирішив "мати сенс" виконати просту дію. На зразок UNIX.
mmr

6
Крім того, що саме робить "Змінити ідентифікатор продукту на *"? Чи створює він щоразу новий ідентифікатор продукту? Чи є наслідки, коли ваш продукт більше не має фіксованого ідентифікатора? - це звучить як надмірність.
Ентоні

10
@Antony, @Dror Helper: Я впевнений, що вам не слід використовувати "*" для створення нового GUID тут. GUID всередині (Upgrade Id = "") повинен бути жорстко закодований і виправлений, і він повинен відповідати GUID у вашому атрибуті (Product UpgradeCode = "").
Джонатан Хартлі

37
Я думаю, вам, мабуть, слід відредагувати свій приклад там, щоб НЕ було фактичного GUID. Я впевнений, що люди будуть копіювати та вставляти це і використовувати його дослівно. Можливо, використовуйте "ВАШЕ-НАПРАВЛІННЯ НАВЧАЛЬНОГО ПРОДУКТА-GUID-ТУТ"?
Коричневий

12
У вашому прикладі є помилка. MSI ProductVersionпідтримує лише три версії поля; тому четверте поле взагалі не буде порівнюватися. Дивіться примітку під VersionMin та VersionMax у msdn.microsoft.com/en-us/library/aa372379(VS.85).aspx
Шрідхар Ратнакумар

89

Далі йде вид синтаксису, який я використовую для великих оновлень:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" Version="$(var.ProductVersion)">
 <Upgrade Id="PUT-GUID-HERE">
    <UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
    <UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>

<InstallExecuteSequence>
    <RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>

Як зауважив @Brian Gillespie, є й інші місця для планування RemoveExistingProducts, залежно від бажаних оптимізацій. Зверніть увагу, що PUT-GUID-ТУТ повинен бути ідентичним.


2
Я читаю розділ "Оновлення та виправлення" в книзі Ніка Раміреса на Wix, і він констатує, що якщо ви плануєте RemoveExistingProducts після InstallInitialize, ви також повинні ПЕРЕДБАЧИТИ графік <InstallExecute After="RemoveExistingProducts" />. У вашому прикладі цього немає - це означає, що книга помиляється?
Вім Коен

3
Я ніколи прямо не планую InstallExecute.
Роб Меншшинг

1
Я не. У WiX v3.6 Burn зробить незначні оновлення легкими у виконанні, але без запису потрібна взаємодія користувача з ручним режимом (доведеться надавати параметри командного рядка), що робить незначні оновлення в основному марними. :)
Роб Меншшинг

1
@RobMensching: як уникнути встановлення старішої версії над новою? Ваша відповідь працює для мене (єдиний приклад "головного оновлення", який я можу отримати для компіляції взагалі з WiX v3.5.2519.0), але можливо встановити старішу версію (після цього я бачу обидві версії в "Додати / Видалити програми ").
Крістіан Шпехт

4
Гаразд, я щойно знайшов у цій відповіді елемент MajorUpgrade, який робить саме те, що я хочу, включаючи запобігання пониженню рівня.
Крістіан Шпехт

40

Елемент "Оновлення" всередині елемента "Продукт" у поєднанні з правильним плануванням дії виконає видалення, яке ви хочете. Обов’язково перелічіть коди оновлення всіх продуктів, які ви хочете видалити.

<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="00000000-0000-0000-0000-000000000000">
  <UpgradeVersion Minimum="1.0.0.0" Maximum="1.0.5.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>

Зауважте, що якщо ви обережно ставитеся до своїх версій, ви можете завадити людям випадково встановити старішу версію вашого продукту на більш новій. Ось для чого поле "Максимальний". Коли ми створюємо інсталяторів, ми встановлюємо UpgradeVersion Maximum до версії, що будується, але IncludeMaximum = "ні", щоб запобігти цьому сценарію.

У вас є вибір щодо планування видалення RemoveExistingProducts. Я вважаю за краще планувати його після InstallFinalize (а не після InstallInitialize, як рекомендували інші):

<InstallExecuteSequence>
  <RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
</InstallExecuteSequence>

Це залишає попередню версію продукту, встановлену до тих пір, поки не будуть скопійовані нові файли та ключі реєстру. Це дозволяє мені переміщувати дані зі старої версії до нової (наприклад, ви переключили зберігання налаштувань користувачів з реєстру на XML-файл, але ви хочете бути ввічливими та перемістити їх налаштування). Ця міграція проводиться у відкладеній спеціальній дії безпосередньо перед InstallFinalize.

Ще одна перевага - ефективність: якщо є незмінні файли, інсталятор Windows не заважає копіювати їх повторно під час планування після InstallFinalize. Якщо ви плануєте після InstallInitialize, попередня версія спочатку повністю видаляється, а потім встановлюється нова версія. Це призводить до непотрібного видалення та повторної копіювання файлів.

Інші параметри планування див. У довідковій статті RemoveExistingProducts в MSDN. На цьому тижні посилання є: http://msdn.microsoft.com/en-us/library/aa371197.aspx


2
@Brian Gillespie: що означає "... якщо є незмінені файли ..."? Які критерії для встановлення Windows вирішують, коли замінити файл, AssemblyVersion, AssemblyFileVersion, розмір файлу, ...?
donttellya

2
@donttellya +1 навчився цьому важко. RemoveExistingProductsбуло заплановано після InstallFinalizeі dlls не оновлювались, оскільки AssemblyVersion був незмінним, але інші поля, такі як AssemblyProduct. Я не хочу бути на милість у програмі порівняння файлів - я просто хочу, щоб попередній додаток GONE
пройшов

16

Можливо, вам буде краще запитати це у списку розсилки користувачів WiX .

WiX найкраще використовувати з чітким розумінням того, що робить Windows Installer. Ви можете розглянути можливість отримання " Повторного керівництва до інсталятора Windows ".

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

RemoveExistingProductsобробляє <Upgrade>елементи в поточній установці, порівнюючи @Idатрибут доUpgradeCode (вказаним у <Product>елементі) всіх встановлених продуктів у системі. UpgradeCodeВизначає сімейство пов'язаних продуктів. Будь-які продукти, що мають цей UpgradeCode, версії яких потрапляють у вказаний діапазон, і де UpgradeVersion/@OnlyDetectатрибут є no(або пропущений), буде видалено.

Документація на RemoveExistingProducts згадує про встановлення UPGRADINGPRODUCTCODEмайна. Це означає, що процес видалення продукту, що вилучається, отримує це властивість, значенням якого єProduct/@Id для встановленого продукту.

Якщо ваша оригінальна установка не включала цю функцію UpgradeCode, ви не зможете використовувати цю функцію.


21
Без сумніву, Майк точно знає, про що він говорить, з усією повагою, але це змушує мене зітхати відчайдушно, споглядаючи, що захаращує мій погляд, чітко розуміючи, що робить інсталятор Windows. Перш ніж я це знаю, я буду займатися консультаційними роботами з Java та .NET для клієнтів Enterprise у прекрасних містах технічного центру, поза межами кільцевої дороги, наповнюючи мої звіти про TPS і цікавлюсь, чому життя здається таким порожнім. Я думаю, що мій наступний проект міг би встановитись із NSIS, який з усіх своїх помилок, як нерозумний мова, схожий на збірку, не дав мені зрозуміти, що робить Windows Installer.
Джонатан Хартлі

2
@Tartley - займіться InnoSetup, що допоможе вам заощадити мову, схожу на збірку :) Переконайтесь, що ви також захопили IStool, він дуже допомагає. Також - погодився, що для простих встановлень все це занадто складно, але я думаю, що їм справді потрібна така складність для встановлення чогось типу SQL Server 2008 ...
Роман Старков

11

Я використовував цей сайт, щоб допомогти мені зрозуміти основи оновлення WiX:

http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization

Після цього я створив зразок Installer (встановив тестовий файл), потім створив інсталятор Upgrade (встановив 2 зразки тестових файлів). Це дасть вам базове розуміння того, як працює механізм.

І як сказав Майк у книзі з Apress "Постійний посібник до інсталятора Windows", це допоможе вам зрозуміти, але це не написано за допомогою WiX.

Ще один дуже корисний сайт - цей:

http://www.wixwiki.com/index.php?title=Main_Page


Приклад на сторінці не працює, як очікувалося, wix.tramontana.co.hu/tutorial/upgrades-and-modularization/… . Я грав із цим. Знизити рівень можливо навіть тоді, коли на сторінці зазначено, що це буде заборонено
sergtk

10

Я читав документацію на WiX , завантажував приклади, але в мене все ще виникало проблем з оновленнями. Незначні оновлення не виконують видалення попередніх продуктів, незважаючи на можливість вказати ці видалення. Я витратив більше цього дня на дослідження і виявив, що WiX 3.5 запровадив новий тег для оновлення. Ось використання:

<MajorUpgrade Schedule="afterInstallInitialize"
        DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." 
        AllowDowngrades="no" />

Але основна причина проблем полягала в тому, що в документації говориться про використання параметрів " REINSTALL = ALL REINSTALLMODE = vomus " для незначних та малих оновлень, але це не говорить про те, що ці параметри заборонені для великих оновлень - вони просто припиняють роботу. Тому не слід використовувати їх для великих оновлень.



7

Одне важливе, що я пропустив з підручників на деякий час (вкрадено з http://www.tramontana.co.hu/wix/lesson4.php ), що призвело до помилок "Інша версія цього продукту вже встановлена":

* Невеликі оновлення означають невеликі зміни в одному або кількох файлах, коли зміна не вимагає зміни версії продукту (major.minor.build). Вам також не потрібно змінювати GUID продукту. Зауважте, що вам завжди потрібно змінити GUID пакета, коли ви створюєте новий .msi-файл, який у будь-якому відношенні відрізняється від попереднього. Інсталятор відслідковує встановлені програми та знаходить їх, коли користувач хоче змінити або видалити інсталяцію за допомогою цих GUID. Використання одного і того ж GUID для різних пакетів збиває з пантелику Установника.

Незначні оновлення позначають зміни, коли версія продукту вже зміниться. Змініть атрибут Version тегу Product. Продукт залишиться тим самим, тому вам не потрібно змінювати GUID продукту, але, звичайно, отримувати новий GUID для упаковки.

Основні оновлення позначають значні зміни, такі як перехід від однієї повної версії до іншої. Змінити все: атрибут версії, GUID на продукт та пакет.


3
Пакет: Тип ідентифікатора: Опис AutogenGuid: GUID коду пакета для продукту чи модуля злиття. При компілюванні продукту цей атрибут не повинен встановлюватися для того, щоб дозволити генерування коду пакета для кожної збірки. Під час компіляції модуля злиття цей атрибут повинен бути встановлений у настанові про модуляризацію. ---- тому нам не потрібно звертати увагу на ідентифікатор пакета, правда?
Cooper.Wu

Ваше посилання мертве
bam500

5

Я використовую найновішу версію WiX (3.0) і не можу переконатись у вищезазначеному. Але це спрацювало:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" ... >

<Upgrade Id="PUT-GUID-HERE">
  <UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
     Minimum="1.0.0.0"  IncludeMinimum="yes"
     Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>

Зауважте, що PUT-GUID-HERE повинен бути таким самим, як і GUID, визначений у властивості UpgradeCode Продукту.


2

Нижче працював для мене.

<Product Id="*" Name="XXXInstaller" Language="1033" Version="1.0.0.0" 
    Manufacturer="XXXX" UpgradeCode="YOUR_GUID_HERE">
<Package InstallerVersion="xxx" Compressed="yes"/>
<Upgrade Id="YOUR_GUID_HERE">
    <UpgradeVersion Property="REMOVINGTHEOLDVERSION" Minimum="1.0.0.0" 
        RemoveFeatures="ALL" />
</Upgrade>
<InstallExecuteSequence>
    <RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>

Переконайтеся, що UpgradeCode в продукті відповідає Ід в оновленнях.


1

Це те, що працювало для мене, навіть з великим рівнем ВНИЗ :

<Wix ...>
  <Product ...>
    <Property Id="REINSTALLMODE" Value="amus" />
    <MajorUpgrade AllowDowngrades="yes" />
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.