Почему файл перезаписывается, если в Wix задан KeyPath

Фрагмент файла Files.wxs, созданный с помощью тепла:

<?xml version="1.0" encoding="utf-8"?>
<Wix
xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Directory Id="dirF5D9BDF13CBC346EDDFD6D0959FFB838" Name="config">
                <Component Id="cmp0CBEDCE6B62E5666B3362D0EB41267BC" Guid="*">
                    <File Id="fil73D1987B7864F07C97735D7E40243AB2" KeyPath="yes"
Source="$(var.App.TargetDir)\config\accounts-example.ini" />
                </Component>
                </Component>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="Binaries">
            <ComponentRef Id="cmp0CBEDCE6B62E5666B3362D0EB41267BC" />
        </ComponentGroup>
    </Fragment>
</Wix>

Product.wxs:

<?xml version="1.0" encoding="utf-8"?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
     xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">
  <Product Id="*" Name="xxx" Language="2052" Version="$(var.ProductVersion)" Manufacturer="xxx"
           UpgradeCode="425BDA6F-31B8-47AD-88D8-4B2DBE394XXX">
    <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

    <MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="New Version [ProductName] has been installed。" />
    <MediaTemplate EmbedCab="yes" />

    <WixVariable Id="WixUILicenseRtf" Value="./License.rtf" />

    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="MANUFACTURERFOLDER" Name="!(bind.property.Manufacturer)">
          <Directory Id="INSTALLFOLDER" Name="!(bind.property.ProductName)" />
        </Directory>
      </Directory>
      <Directory Id="ProgramMenuFolder">
        <Directory Id="ApplicationProgramsFolder" Name="!(bind.property.ProductName)" />
        <Directory Id="DesktopFolder" Name="Desktop" />
      </Directory>
    </Directory>

    <Feature Id="ProductFeature" Title="XXX_Installer" Level="1">
      <ComponentGroupRef Id="Binaries" />
      <ComponentRef Id="ApplicationShortcut" />
      <ComponentRef Id="ApplicationShortcutDesktop" />
      <ComponentRef Id="RegistryEntries" />
    </Feature>

    <UIRef Id="WixUI_ErrorProgressText" />
    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
    <UIRef Id="WixUI_InstallDir" />

    <DirectoryRef Id="ApplicationProgramsFolder">
      <Component Id="ApplicationShortcut" Guid="E1F61345-CC60-40FE-8FC4-FBE1598F8XXX">
        <Shortcut Id="ApplicationStartMenuShortcut"
                  Name="!(bind.property.ProductName)"
                  Description="!(bind.property.ProductName)"
                  Target="[INSTALLFOLDER]XXX_App.exe"
                  WorkingDirectory="INSTALLFOLDER" />
        <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall" />
        <RegistryValue Root="HKCU" Key="Software\Microsoft\!(bind.property.ProductName)" Name="installed" Type="integer" Value="1" KeyPath="yes" />
      </Component>
    </DirectoryRef>
    <DirectoryRef Id="DesktopFolder">
      <Component Id="ApplicationShortcutDesktop" Guid="BEDF111F-0889-4317-8E67-41425F00CXXX">
        <Shortcut Id="ApplicationDesktopShortcut"
                  Name="!(bind.property.ProductName)"
                  Description="!(bind.property.ProductName)"
                  Target="[INSTALLFOLDER]XXX_App.exe"
                  WorkingDirectory="INSTALLFOLDER" />
        <RemoveFolder Id="DesktopFolder" On="uninstall" />
        <RegistryValue Root="HKCU" Key="Software\Microsoft\!(bind.property.ProductName)" Name="installed" Type="integer" Value="1" KeyPath="yes" />
      </Component>
    </DirectoryRef>
    <DirectoryRef Id="TARGETDIR">
      <Component Id="RegistryEntries" Guid="0D919675-E219-43EA-AAB3-E6F81A013XXX">
        <RegistryKey Root="HKCU"
                     Key="Software\Microsoft\Windows\CurrentVersion\Run">
          <RegistryValue Name="!(bind.property.ProductName)"
                         Type="string"
                         Value="[INSTALLFOLDER]XXX_App.exe"/>
        </RegistryKey>
      </Component>
    </DirectoryRef>

    <UI>
      <Publish Dialog="ExitDialog"
          Control="Finish"
          Event="DoAction"
          Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
    </UI>
    <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="启动!(bind.property.ProductName)" />
    <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />

    <Property Id="WixShellExecTarget" Value="[INSTALLFOLDER]XXX_App.exe" />
    <CustomAction Id="LaunchApplication"
        BinaryKey="WixCA"
        DllEntry="WixShellExec"
        Impersonate="yes" />
  </Product>
</Wix>

Каждый раз, когда я устанавливаю новую версию, она перезаписывает существующий файл account-example.ini.

Поведение перезаписи ожидается для account-example.ini, но у меня будет другой файл user.db, который не нужно перезаписывать.

Он говорит, что если для KeyPath установлено значение «да», то он не перезаписывает существующий файл, не так ли? Как мне настроить Wix так, чтобы он перезаписывал один файл и не перезаписывал другой?


Некоторые статьи о KeyPath:

атрибут what-is-the-wix-keypath

copy-if-not-exist-in-wix


person user1633272    schedule 19.03.2017    source источник


Ответы (1)


Если вы делаете это с элементом крупного обновления, вам необходимо сообщить нам, где это запланировано. Если это «рано» (например, afterInstallInitialize), то сначала будет удалено все, а затем будет установлено новое обновление, и все файлы, которые были установлены, будут из нового обновления. Если он упорядочен «поздно» (например, afterInstallExecute), тогда применяются правила перезаписи (например, this https://msdn.microsoft.com/en-us/library/windows/desktop), и это потому, что обновление в основном устанавливает каждый файл поверх существующих файлов.

Обратите внимание, что WiX по умолчанию для расписания MajorUpgrade - afterInstallValidate, поэтому, как я описал (и как говорится в документации WiX), сначала будет удален весь старый продукт (очевидно, удаляются все файлы), а затем будут установлены все новые файлы.

Смотрите расписание здесь:

http://wixtoolset.org/documentation/manual/v3/xsd/wix/majorupgrade.html

Объяснение по ссылке WiX keypath оставляет желать лучшего. Неверно утверждать, что если компонент присутствует, ни один из его ресурсов не будет установлен. Мне не ясно, что это означает, потому что будут применяться правила перезаписи.

Что касается ваших файлов данных, они не будут перезаписаны входящим файлом, если они были обновлены с момента установки. Поэтому вполне вероятно, что ваш ini-файл перезаписывается, потому что он не был изменен. Если ваша база данных была обновлена, она не будет заменена, но, опять же, это правила перезаписи, когда ваше основное обновление «запаздывает» (или это патч).

person PhilDW    schedule 19.03.2017
comment
Я только что добавил Product.wxs в тему. Я изменил установленный файл, а затем переустановил установщик, файл был перезаписан. - person user1633272; 20.03.2017
comment
Смотрите мой развернутый ответ. На самом деле это не перезапись файла. У вас только что запланировано крупное обновление: сначала удалите все файлы, а затем установите новые. Это как если бы вы вручную удалили старый продукт, а затем установили новый. - person PhilDW; 20.03.2017
comment
Как этого избежать? Я имею в виду перезаписать один файл, но не перезаписать другой. - person user1633272; 21.03.2017
comment
Обновление должно быть запланировано после Installexecute, тогда применяются правила перезаписи. Согласно правилам, файл данных не будет перезаписан, если он был обновлен с момента установки, поэтому измененный файл DB или ini не будет перезаписан. Обновлялся ли ini-файл с момента установки? Используете ли вы хеш файла для файлов данных на основе хеша файла MSI? Неясно, хотите ли вы перезаписать ini-файл, потому что считаете это правильным, даже если ваш ini-файл обновления идентичен. - person PhilDW; 21.03.2017
comment
Спасибо. На самом деле я не перезаписываю ini-файл, просто перезаписываю xxx-template.ini, фактический ini изначально создается из template.ini. Я новичок в WiX, поэтому не знаю, как «запланировать обновление после Installexecute». Любую ссылку или документ я могу прочитать? - person user1633272; 21.03.2017
comment
ссылка добавлена ​​к моему ответу - person PhilDW; 21.03.2017