Как изменить RemoveExistingProducts на после InstallFinalize при использовании WixUI_Advanced?

Вот мой сценарий:

  • Использование Wix 3.6
  • Использование набора диалогов WixUI_Advanced (добавляет возможность управлять отдельными функциями во время установки)
  • Установка NeverOverwrite="yes" для компонента web.config (чтобы локальные изменения после установки не были потеряны)

Однако программа установки по-прежнему удаляет и переустанавливает файл web.config во время обновления.

Насколько я могу судить, диалоговый набор WixUI_Advanced настроен примерно так:

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

Вот фрагменты журналов установки:

MSI (s) (74:8C) [18:37:00:959]: Executing op: ActionStart(Name=InstallInitialize,,)
Action 18:37:00: InstallInitialize. 
...
Action 18:37:00: ProcessComponents. Updating component registration
...
Action 18:37:00: UnpublishFeatures. Unpublishing Product Features
...
UnpublishFeatures: Feature: ProductFeature
...
UnpublishFeatures: Feature: AdditionalFeature
...
MSI (s) (74:8C) [18:37:00:967]: Executing op: ActionStart(Name=RemoveFiles,Description=Removing files,Template=File: [1], Directory: [9])
Action 18:37:00: RemoveFiles. Removing files
MSI (s) (74:8C) [18:37:00:967]: Executing op: ProgressTotal(Total=2,Type=1,ByteEquivalent=175000)
MSI (s) (74:8C) [18:37:00:967]: Executing op: SetTargetFolder(Folder=C:\Program Files (x86)\MyTestApp\WebApp\)
MSI (s) (74:8C) [18:37:00:967]: Executing op: FileRemove(,FileName=web.config,,ComponentId={B4A12A8F-56A3-4DD1-A0BA-B9C39EB305FD})
RemoveFiles: File: web.config, Directory: C:\Program Files (x86)\MyTestApp\WebApp\
MSI (s) (74:8C) [18:37:00:968]: Verifying accessibility of file: web.config
MSI (s) (74:8C) [18:37:00:969]: Note: 1: 2318 2:  
MSI (s) (74:8C) [18:37:00:969]: Note: 1: 2318 2:  
MSI (s) (74:8C) [18:37:00:969]: Executing op: FileRemove(,FileName=somefile.txt,,ComponentId={B835CEF5-1A84-4C37-8CB0-BE983BAF73F9})
RemoveFiles: File: somefile.txt, Directory: C:\Program Files (x86)\MyTestApp\WebApp\
MSI (s) (74:8C) [18:37:00:970]: Verifying accessibility of file: somefile.txt
MSI (s) (74:8C) [18:37:00:970]: Note: 1: 2318 2:  
MSI (s) (74:8C) [18:37:00:970]: Note: 1: 2318 2:  
MSI (s) (74:8C) [18:37:00:971]: Executing op: ActionStart(Name=PublishProduct,Description=Publishing product information,)
Action 18:37:00: PublishProduct. Publishing product information
...
Action 18:37:00: RollbackCleanup. Removing backup files
RollbackCleanup: File: C:\Config.Msi\7cd65c.rbf
RollbackCleanup: File: C:\Config.Msi\7cd65d.rbf
MSI (s) (74:8C) [18:37:00:980]: Note: 1: 2318 2:  
MSI (s) (74:8C) [18:37:00:981]: Note: 1: 2318 2:  
MSI (s) (74:8C) [18:37:00:981]: No System Restore sequence number for this installation.
MSI (s) (74:8C) [18:37:00:981]: Unlocking Server
MSI (s) (74:8C) [18:37:00:985]: PROPERTY CHANGE: Deleting UpdateStarted property. Its current value is '1'.
Action ended 18:37:00: InstallFinalize. Return value 1.
Action ended 18:37:00: INSTALL. Return value 1.

Как видите, он удаляет файл web.config после InstallInitialize.

Когда я пытаюсь изменить файл wxs, добавляя:

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

Я получил:

error LGHT0091: Duplicate symbol 'WixAction:InstallExecuteSequence/RemoveExistingProducts' found. This typically means that an Id is duplicated. Check to make sure all your identifiers of a given type (File, Component, Feature) are unique.

Вот файл Product.wxs, который я использую:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
  <Product Id="*" Name="MyTestInstaller" Language="1033" Version="1.0.9.0" Manufacturer="Acme, Inc" UpgradeCode="6ca3779c-e8ce-42e8-bf81-3166bd96e585">
    <Package Id="*" InstallerVersion="301" Compressed="yes" InstallScope="perMachine" Platform="x64" InstallPrivileges="elevated" />

    <Upgrade Id="6ca3779c-e8ce-42e8-bf81-3166bd96e585">
      <UpgradeVersion Minimum="1.0.9.0" OnlyDetect="yes" Property="NEWERVERSIONDETECTED" />
      <UpgradeVersion OnlyDetect="no" Minimum="0.0.0.0" IncludeMinimum="yes" Maximum="1.0.9.0" Property="OLDERVERSIONBEINGUPGRADED" IgnoreRemoveFailure="yes">
      </UpgradeVersion>
    </Upgrade>

    <Condition Message="A later version of [ProductName] is already installed.">NOT NEWERVERSIONDETECTED</Condition>
    <Media Id="1" Cabinet="myapp.cab" EmbedCab="yes" />
    <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
    <Feature Id="ProductFeature" Title="MyTestInstaller" Level="1">
      <ComponentGroupRef Id="ProductComponents" />
    </Feature>
    <Feature Id="AdditionalFeature" Title="Additional Features" Level="10">
      <ComponentGroupRef Id="AdditionalComponents"/>
    </Feature>
    <Property Id="ApplicationFolderName" Value="MyTestApp"/>
    <!-- BEGIN: DISABLE THE Per User Install -->
    <Property Id="WixAppFolder" Value="WixPerMachineFolder"/>
    <WixVariable Id="WixUISupportPerUser" Value="0" />
    <!-- END: DISABLE THE Per User Install -->
    <UI>
      <UIRef Id="WixUI_Advanced" />
    </UI>
  </Product>

  <Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="APPLICATIONFOLDER" Name="ICS">
          <Directory Id="WebApp" Name="WebApp">
            <Component Id="WEB.CONFIG" Guid="B4A12A8F-56A3-4DD1-A0BA-B9C39EB305FD" DiskId="1" NeverOverwrite="yes">
              <File Id="WEB.CONFIG" Name="web.config" Source="web.config" KeyPath="yes"/>
            </Component>
            <Component Id="SOMEFILE" DiskId="1" Guid="B835CEF5-1A84-4C37-8CB0-BE983BAF73F9">
              <File Id="SOMEFILE" Name="somefile.txt" Source="somefile.txt" KeyPath="yes"/>
              <util:XmlConfig Id="WEBCFG_1" File="[WebApp]Web.config" Action="create" Node="element" Name="module" ElementPath="/configuration/autofac/modules" VerifyPath="/configuration/autofac/modules/module[\[]@type='ICS.Automation.JDE.Base.JDEModule, ICS.Automation.JDE.Base'[\]]" Sequence="10" On ="install" />
              <util:XmlConfig Id="WEBCFG_2" ElementId="WEBCFG_1" File="[WebApp]Web.config" Name="type" Value="MyDll, MyDll" Sequence="11" />
            </Component>
          </Directory>
        </Directory>
      </Directory>
    </Directory>
  </Fragment>

  <Fragment>
    <ComponentGroup Id="ProductComponents">
      <ComponentRef Id="WEB.CONFIG"/>
    </ComponentGroup>
    <ComponentGroup Id="AdditionalComponents">
      <ComponentRef Id="SOMEFILE"/>
    </ComponentGroup>
  </Fragment>
</Wix>

Как я могу изменить RemoveExistingProducts, чтобы они шли после InstallFinalize? В конце концов, мне просто нужно, чтобы этот файл никогда не перезаписывался.

Спасибо!


person brendonparker    schedule 03.01.2018    source источник


Ответы (1)


Тег MajorUpgrade является предпочтительным способом выполнения обновления, и он будет упорядочивать RemoveExistingProducts (REP) везде, где вы укажете, что должно частично упростить это. Пользовательскому интерфейсу нет причин перемещать REP.

По умолчанию для планирования REP используется после InstallValidate, что в основном представляет собой удаление старого продукта с последующей установкой обновления, поэтому это не столько обновление/перезапись файла конфигурации, сколько удаление/удаление с последующей новой установкой.

Если REP запланирован после установкиInstallExecute, то во время обновления применяются правила перезаписи (поскольку обновление «перезаписывает» существующий установленный продукт перед его удалением). Файл web.config просто должен иметь один и тот же идентификатор компонента как в старых, так и в новых продуктах, и если он действительно был изменен после его установки, то правила перезаписи должны означать, что он не будет перезаписан.

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370531(v=vs.85).aspx

Другими словами, просто используйте основной элемент обновления с afterInstallExecute, имейте одинаковые идентификаторы компонентов как в старых, так и в новых ресурсах (файлах и т. д.), и файл web.config не должен быть перезаписан, и вам не нужно устанавливать neveroverwrite.

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

person PhilDW    schedule 03.01.2018
comment
Как насчет этого сценария (в хронологическом порядке) 1) Установить 2) Обновить установленную конфигурацию 3) Обновить конфигурацию, создать новый msi 4) запустить установку. Будет ли установленный сейчас конфиг от 2, или от 3? Я бы хотел, чтобы это было из 2. В основном не обновляйте конфигурацию после первоначальной установки. Я был бы в порядке, если бы файл обновлялся только в том случае, если он отсутствует (если он был удален по какой-то причине). - person brendonparker; 04.01.2018
comment
Если на шаге 2) пользователь изменяет файл (а не установщик), результатом после шага 4 будет версия шага 2). - person RFlum; 05.05.2019