Я наконец-то получил подход RegistrySearch. Я надеюсь, что это может помочь другим людям в будущем.
Я проверил документацию MSI. Таблица реестра фактически не содержит столбец с именем type. Вместо этого он хранит значение странным образом, поэтому MSI знает, какой тип значения реестра следует создать. В моем случае я хочу создать значение реестра типа DWORD. Значение должно храниться как # 1 в таблице реестра, если я хочу поместить числовое значение 1 в значение реестра. Вот ссылка на Реестр таблицы
Итак, почему Wix RegistryValue имеет обязательный атрибут Type? Я думаю, это потому что Викс пытается быть с тобой добрым. Если вы пометите тип как int, вы можете просто ввести «1» в атрибуте value. Вам не нужно помнить, что вы должны ввести «# 1» вместо «1». Когда вы компилируете исходный код Wix, компилятор сделает за вас грязную работу и переведет «1» в «# 1».
Аналогично, RegistrySearch является прямым отображением таблицы базы данных MSI RegLocator. Это возвращает # 1 мне, потому что мой тип значения реестра - DWORD. Жаль, что Викс на этот раз не сделал для меня перевод. Следующий код возвращает мне необработанные данные из таблицы. Итак, мое свойство LOG_LEVEL хранит # 1 вместо 1.
<Property Id='LOG_LEVEL' Value='3'>
<RegistrySearch Id='LogLevelRegistry' Type='raw' Root='HKLM' Key='Software\Company\Product' Name='LogLevel' Win64='$(var.Win64)'/>
</Property>
Вот ссылка для RegistrySearch
Мой код сохранил значение реестра в свойстве. Затем я пытался вернуть его, используя следующий код.
<Component Id="RegistryKey">
<RegistryKey Root='HKLM' Key='Software\Company\Product' Action='createAndRemoveOnUninstall'>
<RegistryValue Type='int' Name='LogLevel' Value='[LOG_LEVEL]'/>
</RegistryKey>
</Component>
Как я уже сказал, Wix добавит # для меня, когда увидит тип "int". Итак, значение в таблице Registry теперь равно ## 1. Если вы проверите документ MSDN, ## 1 будет интерпретироваться как строковое значение "# 1". Поэтому значение моего реестра воссоздается с новым типом SZ и новым значением "# 1"
Чтобы исправить эту проблему, я изменил свой код на этот
<Property Id='LOG_LEVEL' Value='#3'>
<RegistrySearch Id='LogLevelRegistry' Type='raw' Root='HKLM' Key='Software\Company\Product' Name='LogLevel' Win64='$(var.Win64)'/>
</Property>
<Component Id="RegistryKey">
<RegistryKey Root='HKLM' Key='Software\Company\Product' Action='createAndRemoveOnUninstall'>
<RegistryValue Type='string' Name='LogLevel' Value='[LOG_LEVEL]'/>
</RegistryKey>
</Component>
Обратите внимание, что хотя я здесь указываю тип "строка", у меня все еще есть значение реестра с типом DWORD, созданное для меня. Это потому, что MSI интерпретирует значение в таблице Registry. Если значение реестра LogLevel не существует (новая установка), я установлю для него значение по умолчанию # 3. Если значение реестра LogLevel существует, оно сохранит существующий LogLevel.
Также обратите внимание, что этот метод работает, потому что Wix 3.0 не выполняет никакой обработки значения свойства. Он помещает значение, хранящееся в свойстве, непосредственно в таблицу Registry.
Просто из любопытства я также попробовал следующее.
<RegistryValue Type='string' Name='LogLevel' Value='#1'/>
На этот раз Wix правильно экранировал символ # и поместил ## 1 в таблицу Registry. Если позже Wix решит также экранировать символ # внутри значения свойства, мое решение здесь не будет работать.