Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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.