Можно ли использовать данные, полученные при использовании 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.

SetRegistry1.zip