Is it possible to use RegistrySearch result in RegistryValue?


Русская версия здесь.


 


This post is an answer to this question sent to wix-users mailing list:


Is it possible to use RegistrySearch result in RegistryValue? Something like this:


 


<Property Id=”PROP1″>


    <RegistrySearch Id=”search1″


                    Root=”HKLM”


                    Key=”somekey”


                    Name=”somename”


                    Type=”raw” />


</Property>





<RegistryValue Type=”???” Name=”othervalue” Value=”PROP1″ />


 


First of all, in order to use property, desired field must have Formatted data type.  Quick look to Registry table and RegistryValue element reveals that both Value column and Value attribute are in fact Formatted.  So, we are good to go.  The only change we need to make is to set Value attribute to:


<RegistryValue Type=”???” Name=”othervalue” Value=”[PROP1]” /> 


Now, how about Type attribute?  What value do we need to use?


Description for Registry table is stating that normally the value of Value column is treated as string (REG_SZ) unless it is prefixed with one of the special prefixes or contains the sequence tilde [~]:


















Prefix Meaning
#x Hexadecimal value (REG_BINARY)
#% Expandable string (REG_EXPAND_SZ)
# Integer (REG_DWORD)
Contains [~] Null-delimited list of strings (REG_MULTI_SZ).

That means that we should be able to always use Type=”string” provided that we properly format values.  This fragment successfully proves that:


<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>



So, how we can format data we read from registry during AppSearch?  Quick look at RegLocator table reveals that Windows Installer adds a prefix to the registry value that identifies the type of registry value.  Cool.  Let’s test it to see if we already get the value we need:


<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>


As you can see, I collected registry values during AppSearch and then used Custom Action Type 51 to set other properties with collected values, but preprended with “..”.  I did it because I want these values to be interpreted as strings.


It was expected that multi-string value will show up as multi-string, because its interpretation is based on presense of [~] and not on any particular prefix.  What is surprising is that expanded string property did show up as expanded and not prefixed with #% whereas description of RegLocator table clearly stating that it should be the case.


So, with the exception of expanded strings, all we need to do is to write values read during AppSearch to registry unchanged:


<?xml version=1.0 encoding=UTF-8?>


<Wix xmlns=http://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>



So, the answer is – Yes, unless we want to preserve expandable string value.


 


Source code is in attachement.


 

SetRegistry1.zip

Comments (2)

  1. Neil Sleightholm says:

    Alex, useful post but could you explain the prepending .. bit, I am not sure what this was for.

  2. Alex Shevchuk says:

    Sorry, the idea was that to add integer 2 to registry value we need to add prefix ‘#’ to it. So, writing <RegistryValue Type="string" Value="#2" … /> will actually create registry value of type REG_DWORD with value 2. Description for RegLocator is saying that REG_DWORD value 2 will be represented during AppSearch as string value "#2" in property.  Because I wanted to show actual string read from registry during AppSearch, I prepended it with ".." so during writing this value to registry it will be treated as string, not as REG_DWORD.

    I think, I need to clarify it little bit better.  I’ll think about it tomorrow.

    Thanks,

    Alex