Как сохранить значения свойств использовавшихся при начальной установке

English version is here.

 

Один из наиболее часто задаваемых вопросов - как сохранить значение свойства, которое было присвоено свойству во время инсталлирования программы (присвоенное либо через параметер в командной строке или через пользовательский интерфейс как, например, INSTALLLOCATION).

В качестве примера возьмем одну из возможный ситуатций. Рассмотрим очень простой пример. Идея состоит в том, что пользователь передает через командную строку значение, которое необходимо записать в XML файл.  Также, необходимо чтобы это значение осталось неизменным при "починке" (repair).  Начнем с очень простого примера:

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

<Wix xmlns="https://schemas.microsoft.com/wix/2006/wi"

     xmlns:util="https://schemas.microsoft.com/wix/UtilExtension">

  <?define UpgradeCode="{D1C829D8-5A5B-412C-90ED-7F92750F8152}"?>

  <?define CurrentVersion="1.0.0.0"?>

  <Product Id="*"

           Name="PreserveProperty"

           Language="1033"

           Version="$(var.CurrentVersion)"

           Manufacturer="PreserveProperty"

           UpgradeCode="$(var.UpgradeCode)">

    <Package InstallerVersion="200"

             Compressed="yes"

             InstallScope="perMachine"

             Languages="1033" />

    <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

<!-- Make sure properties are passed in the command line -->

<Condition Message="MYPROPERTY variable must be set in the command line">

Installed OR MYPROPERTY

</Condition>

    <!-- Installation -->

    <Directory Id="TARGETDIR" Name="SourceDir">

      <Directory Id="ProgramFilesFolder">

        <Directory Id="INSTALLLOCATION" Name="PreserveProperty">

          <Component Id="ProductComponent"

                    Guid="cf13f922-e33c-4b78-a849-46e32c000e09">

            <File Id="XmlFile"

                 Name="test.xml"

                 Source="test.xml"

                 KeyPath="yes" />

            <util:XmlFile Id="SetMYPROPERTY"

                  Action="setValue"

                          ElementPath="//config/parameter[\[]@name='MyProperty'[\]]/@value"

                          Value="[MYPROPERTY]"

                          File="[#XmlFile]" />

           

          </Component>

        </Directory>

      </Directory>

    </Directory>

    <Feature Id="ProductFeature" Title="PreserveProperty" Level="1">

      <ComponentRef Id="ProductComponent" />

    </Feature>

  </Product>

</Wix>

Для того чтобы проверить, что свойство MYPROPERTY было включено в командную строку, используется Custom Action Type 19 (элемент <Condition>).

Во время установки, инсталлятор скопирует файл install test.xml и установит значение атрибута value в значение свойства MYPROPERTY.  Файл test.xml выглядит следующим образом:

<config>

 <parameter name='MyProperty' value='' />

</config>

Если Вы скомпилируете пример и установите его, то Вы увидите, что файл test.xml создан и значение атрибута value то же, что и переданное через командную строку.  Попробуйте установить пример используя следующую командную строку:

msiexec /i PreserveProperty.msi MYPROPERTY="123"

Можно также попробовать и без свойства MYPROPERTY в командной строке.  Программа выдаст сообщение об ошибке из элемента <Condition>.

Теперь, попробуем починить инсталляцию.  Это можно сделать через Add/Remove Programs, меню Repair.  После того, как починка окончена, откройте файл test.xml.  Вы увидите, что значение атрибута value пусто.  Проблема в том, что MYPROPRTY="123" не было использовано при запуске msiexec.exe. Нашей обязанностью является сохранение значения свойства переданного msiexec.exe во время первоначальной установки.

Давайте внесем изменения в наш WiX файл:

  1. Сохраним значение свойства в реестре (registry)
  2. Восстановим значение свойства из реестра во время AppSearch (будем использовать временное свойство)
  3. Скопируем значение временного свойства в MYPROPRTY при условии, что это НЕ начальная установка

Первый пункт простой:

<RegistryKey Id="PreservePropertyInRegistry"

  Root="HKLM"

  Key="SOFTWARE\ACME Corp" Action="createAndRemoveOnUninstall">

  <RegistryValue Id="SavedProperty"

  Action="write"

  Type="string"

  Name="SavedProperty"

   Value="[MYPROPERTY]" />

</RegistryKey>

Второй пункт - обычный RegistrySearch: 

<Property Id="SAVEDMYPROPERTY" Secure="yes">

  <RegistrySearch Id="FindSavedMYPROPERTY"

                  Root="HKLM"

                  Key="SOFTWARE\ACME Corp"

                  Name="SavedProperty"

                  Type="raw"

                  Win64="no" />

</Property>

Третий пункт - элемент <SetProperty> (или Custom Action Type 51, если Вы все еще используете версию V2), но с добавленным условием, что программа уже установлена.

<SetProperty Id="MYPROPERTY" After="AppSearch" Value="[SAVEDMYPROPERTY]">

  Installed

</SetProperty>

Исходный код в attachment. 

 

PreserveProperty.zip