Можно ли использовать данные, полученные при использовании RegistrySearch в RegistryValue
English version is here.
Вопрос:
Можно ли использовать данные, полученные при использовании RegistrySearch в RegistryValue? Нечто вроде этого:
<Property Id="PROP1">
<RegistrySearch Id="search1"
Root="HKLM"
Key="somekey"
Name="somename"
Type="raw" />
</Property>
...
<RegistryValue Type="???" Name="othervalue" Value="PROP1" />
Прежде всего, для того чтобы использовать свойство необходимо, чтобы атрибут элемента имел тип данных Formatted. Документация по таблице Registry и элементу RegistryValue указывает, что как колонка Value, так и атрибут Value на самом деле являются Formatted. Так что мы можем продолжить. Единственное, что нам надо изменить, это значение атрибута Value:
<RegistryValue Type="???" Name="othervalue" Value="[PROP1]" />
Теперь, как насчет атрибута Type? Какое значение он должен иметь?
В документации по таблице Registry говорится о том, что обычно значение в колонке Value будет интерпретировано как строка (REG_SZ) при условии, что значение не имеет в начале строки один из специальных префиксов и не содержит тильда последовательностей [~]:
Префикс | Значение |
---|---|
#x | Шестнадцатеричное число (REG_BINARY) |
#% | Расширяемая (еxpandable) строка (REG_EXPAND_SZ) |
# | Целое число (REG_DWORD) |
Contains [~] | Список строк разделенных друг от друга значением Null (REG_MULTI_SZ). |
Это означает, что мы можем использовать Type="string" при условии, что мы дадим правильный формат значениям. Следующий фрагмент успешно доказывает это:
<SetProperty Id="STRINGPROPCONST" After="AppSearch" Value="QWERTY" />
<SetProperty Id="DWORDPROPCONST" After="AppSearch" Value="#2" />
<SetProperty Id="EXPANDSZPROPCONST" After="AppSearch" Value="#%%SystemRoot%\System32\svchost.exe" />
<SetProperty Id="BINARYPROPCONST" After="AppSearch" Value="#x0123456789ABCDEF" />
<SetProperty Id="MULTISZPROPCONST" After="AppSearch" Value="a[~]b[~]c" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="INSTALLLOCATION" Name="SetRegistry1">
<Component Id="ProductComponent"
Guid="f4ca4e76-d04a-4b89-9a1a-7a666a42a635">
<CreateFolder />
<RemoveFolder Id="RemoveMe" On="uninstall" />
<RegistryKey Id="TestValue"
Root="HKCU"
Key="ACME Corp"
Action="createAndRemoveOnUninstall">
<RegistryValue Id="StringValueConst"
Type="string"
Action="write"
Name="StringPropertyConst"
Value="[STRINGPROPCONST]" />
<RegistryValue Id="DWordValueConst"
Type="string"
Action="write"
Name="DWordPropertyConst"
Value="[DWORDPROPCONST]" />
<RegistryValue Id="ExpandSzValueConst"
Type="string"
Action="write"
Name="ExpandPropertyConst"
Value="[EXPANDSZPROPCONST]" />
<RegistryValue Id="BinaryValueConst"
Type="string"
Action="write"
Name="BinaryPropertyConst"
Value="[BINARYPROPCONST]" />
<RegistryValue Id="MultiSzValueConst"
Type="string"
Action="write"
Name="MultiSzPropertyConst"
Value="[MULTISZPROPCONST]" />
</RegistryKey>
</Component>
</Directory>
</Directory>
</Directory>
Теперь, как нам отформатировать данные, прочитанные из реестра (registry) во время AppSearch? В документации по таблице RegLocator говорится о том, что Windows Installer сам добавит префикс, соответствующий типу данных в реестре к значению из реестра. Здорово. Давайте проверим, так ли это на самом деле:
<Property Id="STRINGPROP">
<RegistrySearch Id="Search1"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="ObjectName"
Type="raw"
Win64="no"/>
</Property>
<Property Id="DWORDPROP">
<RegistrySearch Id="Search2"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="Start"
Type="raw"
Win64="no"/>
</Property>
<Property Id="EXPANDSZPROP">
<RegistrySearch Id="Search3"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="ImagePath"
Type="raw"
Win64="no"/>
</Property>
<Property Id="BINARYPROP">
<RegistrySearch Id="Search4"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="FailureActions"
Type="raw"
Win64="no"/>
</Property>
<Property Id="MULTISZPROP">
<RegistrySearch Id="Search5"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="DependOnService"
Type="raw"
Win64="no"/>
</Property>
<SetProperty Id="STRINGPROPRAW" After="AppSearch" Value="..[STRINGPROP]" />
<SetProperty Id="DWORDPROPRAW" After="AppSearch" Value="..[DWORDPROP]" />
<SetProperty Id="EXPANDSZPROPRAW" After="AppSearch" Value="..[EXPANDSZPROP]" />
<SetProperty Id="BINARYPROPRAW" After="AppSearch" Value="..[BINARYPROP]" />
<SetProperty Id="MULTISZPROPRAW" After="AppSearch" Value="..[MULTISZPROP]" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="INSTALLLOCATION" Name="SetRegistry1">
<Component Id="ProductComponent"
Guid="f4ca4e76-d04a-4b89-9a1a-7a666a42a635">
<CreateFolder />
<RemoveFolder Id="RemoveMe" On="uninstall" />
<RegistryKey Id="TestValue"
Root="HKCU"
Key="ACME Corp"
Action="createAndRemoveOnUninstall">
<RegistryValue Id="StringValueRaw"
Type="string"
Action="write"
Name="StringPropertyRaw"
Value="[STRINGPROPRAW]" />
<RegistryValue Id="DWordValueRaw"
Type="string"
Action="write"
Name="DWordPropertyRaw"
Value="[DWORDPROPRAW]" />
<RegistryValue Id="ExpandSzValueRaw"
Type="string"
Action="write"
Name="ExpandPropertyRaw"
Value="[EXPANDSZPROPRAW]" />
<RegistryValue Id="BinaryValueRaw"
Type="string"
Action="write"
Name="BinaryPropertyRaw"
Value="[BINARYPROPRAW]" />
<RegistryValue Id="MultiSzValueRaw"
Type="string"
Action="write"
Name="MultiSzPropertyRaw"
Value="[MULTISZPROPRAW]" />
</RegistryKey>
</Component>
</Directory>
</Directory>
</Directory>
Как Вы видите, я сохранил значения из реестра в свойствах во время исполнения AppSearch и затем использовал Custom Action Type 51 для того, чтобы скопировать их в другие свойства, но с добавлением двух точек в начале строки. Я сделал это для того, чтобы позже сохранить эти значения в реестре именно как строки, а не как другие типы данных.
Нет ничего удивительного в том, что мульти-строковые (multi-string) значения записаны в реестр как мульти-строковые, поскольку их интерпретация зависит от наличия [~] в строке, а не от того, с какого префикса они начинаются. Что удивительно, это то что расширенные (expanded) строки записаны в реестр как уже преобразованные в строку, а не непреобразованное значение с префиксом #% , хотя документация по таблице RegLocator ясно говорит о том, что именно это и должно быть результатом.
Так что, за исключением expanded строк, все что нам нужно, это сохранить считанные во время AppSearch данные в реестр без каких либо изменений:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="https://schemas.microsoft.com/wix/2006/wi">
<Product Id="30eb65de-f04a-4a79-a153-4542687b7515"
Name="SetRegistry1"
Language="1033"
Version="1.0.0.0"
Manufacturer="SetRegistry1"
UpgradeCode="da268df3-4a01-41de-8c09-a8c11abee160">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perUser" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Property Id="STRINGPROP">
<RegistrySearch Id="Search1"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="ObjectName"
Type="raw"
Win64="no"/>
</Property>
<Property Id="DWORDPROP">
<RegistrySearch Id="Search2"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="Start"
Type="raw"
Win64="no"/>
</Property>
<Property Id="EXPANDSZPROP">
<RegistrySearch Id="Search3"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="ImagePath"
Type="raw"
Win64="no"/>
</Property>
<Property Id="BINARYPROP">
<RegistrySearch Id="Search4"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="FailureActions"
Type="raw"
Win64="no"/>
</Property>
<Property Id="MULTISZPROP">
<RegistrySearch Id="Search5"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\services\wscsvc"
Name="DependOnService"
Type="raw"
Win64="no"/>
</Property>
<SetProperty Id="STRINGPROPCONST" After="AppSearch" Value="QWERTY" />
<SetProperty Id="DWORDPROPCONST" After="AppSearch" Value="#2" />
<SetProperty Id="EXPANDSZPROPCONST" After="AppSearch" Value="#%%SystemRoot%\System32\svchost.exe" />
<SetProperty Id="BINARYPROPCONST" After="AppSearch" Value="#x0123456789ABCDEF" />
<SetProperty Id="MULTISZPROPCONST" After="AppSearch" Value="a[~]b[~]c" />
<SetProperty Id="STRINGPROPRAW" After="AppSearch" Value="..[STRINGPROP]" />
<SetProperty Id="DWORDPROPRAW" After="AppSearch" Value="..[DWORDPROP]" />
<SetProperty Id="EXPANDSZPROPRAW" After="AppSearch" Value="..[EXPANDSZPROP]" />
<SetProperty Id="BINARYPROPRAW" After="AppSearch" Value="..[BINARYPROP]" />
<SetProperty Id="MULTISZPROPRAW" After="AppSearch" Value="..[MULTISZPROP]" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="INSTALLLOCATION" Name="SetRegistry1">
<Component Id="ProductComponent"
Guid="f4ca4e76-d04a-4b89-9a1a-7a666a42a635">
<CreateFolder />
<RemoveFolder Id="RemoveMe" On="uninstall" />
<RegistryKey Id="TestValue"
Root="HKCU"
Key="ACME Corp"
Action="createAndRemoveOnUninstall">
<RegistryValue Id="StringValueConst"
Type="string"
Action="write"
Name="StringPropertyConst"
Value="[STRINGPROPCONST]" />
<RegistryValue Id="DWordValueConst"
Type="string"
Action="write"
Name="DWordPropertyConst"
Value="[DWORDPROPCONST]" />
<RegistryValue Id="ExpandSzValueConst"
Type="string"
Action="write"
Name="ExpandPropertyConst"
Value="[EXPANDSZPROPCONST]" />
<RegistryValue Id="BinaryValueConst"
Type="string"
Action="write"
Name="BinaryPropertyConst"
Value="[BINARYPROPCONST]" />
<RegistryValue Id="MultiSzValueConst"
Type="string"
Action="write"
Name="MultiSzPropertyConst"
Value="[MULTISZPROPCONST]" />
<RegistryValue Id="StringValueRaw"
Type="string"
Action="write"
Name="StringPropertyRaw"
Value="[STRINGPROPRAW]" />
<RegistryValue Id="DWordValueRaw"
Type="string"
Action="write"
Name="DWordPropertyRaw"
Value="[DWORDPROPRAW]" />
<RegistryValue Id="ExpandSzValueRaw"
Type="string"
Action="write"
Name="ExpandPropertyRaw"
Value="[EXPANDSZPROPRAW]" />
<RegistryValue Id="BinaryValueRaw"
Type="string"
Action="write"
Name="BinaryPropertyRaw"
Value="[BINARYPROPRAW]" />
<RegistryValue Id="MultiSzValueRaw"
Type="string"
Action="write"
Name="MultiSzPropertyRaw"
Value="[MULTISZPROPRAW]" />
<RegistryValue Id="StringValue"
Type="string"
Action="write"
Name="StringProperty"
Value="[STRINGPROP]" />
<RegistryValue Id="DWordValue"
Type="string"
Action="write"
Name="DWordProperty"
Value="[DWORDPROP]" />
<RegistryValue Id="ExpandSzValue"
Type="string"
Action="write"
Name="ExpandProperty"
Value="[EXPANDSZPROP]" />
<RegistryValue Id="BinaryValue"
Type="string"
Action="write"
Name="BinaryProperty"
Value="[BINARYPROP]" />
<RegistryValue Id="MultiSzValue"
Type="string"
Action="write"
Name="MultiSzProperty"
Value="[MULTISZPROP]" />
</RegistryKey>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="SetRegistry1" Level="1">
<ComponentRef Id="ProductComponent" />
</Feature>
</Product>
</Wix>
Итак, ответ на первоначальный вопрос - Да, если только мы не собираемся сохранять expandable строки.
Исходный код в attachement.