Как реализовать обновление установщика WiX?

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

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

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

229
задан Peter Mortensen 30 January 2010 в 15:15
поделиться

8 ответов

В новейших версиях (начиная с бета-версии 3.5.1315.0) вы можете использовать элемент MajorUpgrade вместо своего собственного.

Например, мы используем этот код для автоматического обновления. Он предотвращает понижение версии, выдавая локализованное сообщение об ошибке, а также предотвращает обновление уже существующей идентичной версии (т.е. обновляются только более низкие версии):

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />
182
ответ дан 23 November 2019 в 03:43
поделиться

Наконец я нашел решение - я отправляю его здесь для других людей, у которых могла бы быть та же проблема (все 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" /> 
    

С этого времени каждый раз, когда я устанавливаю продукт, он удалил предыдущие установленные версии.

Примечание: идентификатор обновления замены с Вашим собственным GUID

219
ответ дан ssingh3 23 November 2019 в 03:43
поделиться

Элемент Обновления в элементе продукта, объединенном с надлежащим планированием действия, выполнит удаление, которое Вы после. Обязательно перечислите коды обновления всех продуктов, которые Вы хотите удалить.

<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>

Примечание, что, если Вы осторожны со своими сборками, можно предотвратить людей от случайной установки более старой версии продукта по более новому. Это - то, для чего поле Maximum. Когда мы создаем установщики, мы устанавливаем Максимум UpgradeVersion на создаваемую версию, но IncludeMaximum = "нет" для предотвращения этого сценария.

у Вас есть выбор относительно планирования RemoveExistingProducts. Я предпочитаю планировать его после InstallFinalize (а не после InstallInitialize, как другие рекомендовали):

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

Это оставляет предыдущую версию продукта установленной до окончания новых файлов, и ключи реестра копируются. Это позволяет мне переместить данные от старой версии до нового (например, Вы переключили устройство хранения данных пользовательских настроек от реестра до XML-файла, но Вы хотите быть вежливыми и переместить их настройки). Эта миграция сделана в задержанном пользовательском действии незадолго до InstallFinalize.

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

Для других опций планирования, посмотрите тему справки RemoveExistingProducts в MSDN. На этой неделе ссылка: http://msdn.microsoft.com/en-us/library/aa371197.aspx

40
ответ дан Brian Gillespie 23 November 2019 в 03:43
поделиться

Вы могли бы лучше спрашивать это относительно эти WiX-пользовательский список рассылки .

WiX лучше всего используется с твердым пониманием того, что делает Windows Installer. Вы могли бы рассмотреть получение" Полное руководство к Windows Installer ".

действие, которое удаляет существующий продукт, действие RemoveExistingProducts . Поскольку последствия того, что это делает, зависят от того, где это запланировало - а именно, заставляет ли отказ старый продукт быть переустановленным, и копируются ли неизменные файлы снова - необходимо запланировать его сами.

RemoveExistingProducts процессы <Upgrade> элементы в текущей установке, соответствуя эти @Id атрибут к UpgradeCode (определенный в <Product> элемент) всех установленных продуктов в системе. Эти UpgradeCode определяет семью сопутствующих товаров. Будут удалены любые продукты, которые имеют этот UpgradeCode, версии которого попадают в диапазон, определенный, и где эти UpgradeVersion/@OnlyDetect атрибут no (или опущен).

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

, Если Ваша исходная установка не включала UpgradeCode, Вы не будете в состоянии использовать эту функцию.

15
ответ дан Cœur 23 November 2019 в 03:43
поделиться

Я использовал этот сайт, чтобы помочь мне понять основы об Обновлении WiX:

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

Впоследствии я создал демонстрационный Установщик, (установил тестовый файл), затем создал установщик Обновления (установил 2 демонстрационных тестовых файла). Это даст Вам основное понимание того, как механизм работает.

И поскольку Mike сказал в книге от Apress, "Полное руководство к Windows Installer", это выручит Вас для понимания, но это не записано с помощью WiX.

Другой сайт, который был довольно полезен, был этим:

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

11
ответ дан Rob W 23 November 2019 в 03:43
поделиться

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

<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-HERE должен быть идентичным.

88
ответ дан Rob Mensching 23 November 2019 в 03:43
поделиться

Предлагаю взглянуть на учебник Алекса Шевчука. Он объясняет «серьезное обновление» через WiX на хорошем практическом примере в От MSI до WiX, часть 8 - Основное обновление .

7
ответ дан 23 November 2019 в 03:43
поделиться

Я использую последнюю версию 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 продукта.

5
ответ дан 23 November 2019 в 03:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: