Как сохранить значения свойств использовавшихся при начальной установке
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 файл:
- Сохраним значение свойства в реестре (registry)
- Восстановим значение свойства из реестра во время AppSearch (будем использовать временное свойство)
- Скопируем значение временного свойства в 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.