6

I've created an installer with WiX and am trying to preserve an existing DWORD registry entry during a repair installation of my product. To store the existing values, I am using the following WiX fragment;

<Property Id="PreserveMySetting" Secure="yes">
  <RegistrySearch Id="FindExistingMySetting"
                  Root="HKLM"
                  Key="Software\!(loc.ProductManufacturer)\!(loc.ProductName)"
                  Name="MySetting"
                  Type="raw"
                  Win64="no" />
</Property>

I then set this later on using a component driven by the saved value.

The problem is, the registry search returns the DWORD as a "Formatted" string, e.g.;

#1

Instead of just

1

This means that when my component sets the registry entry, it is created as a REG_SZ with the value "#1", even though I've indicated that it should be an integer;

<Component Id="MySettingKey"
    Guid="{76C4B14C-14BC-42E1-91F0-75C9F2A20EC8}">
    <RegistryValue Id="MySetting"
        Action="write"
        Name="MySetting"
        Value="[PreserveMySetting]"
        Type="integer"
        KeyPath="yes"
        Key="Software\!(loc.ProductManufacturer)\!(loc.ProductName)"
        Root="HKMU"/>
</Component>

Is there any way to get the actual registry value for use by the component?

Chris McAtackney
  • 5,192
  • 8
  • 45
  • 69

1 Answers1

9

This is going to sound backwards, but if you change the Type attribute to string it'll work. The reason is clear when you look at your MSI's Registry table using ORCA.

When you select integer WiX author's "#[PRESERVEMYSETTING]" and when you select string it author's [PRESERVEMYSETTING]. Since PRESERVEMYSETTING is already #1 you want it to be #1 not ##1.

<Component Id="MySettingKey" 
    Guid="{76C4B14C-14BC-42E1-91F0-75C9F2A20EC8}">
    <RegistryValue Id="MySetting"
        Action="write"
        Name="MySetting"
        Value="[PRESERVEMYSETTING]" <!-- Secure Properties are PUBLIC properties -->
        Type="string"
        KeyPath="yes"
        Key="Software\!(loc.ProductManufacturer)\!(loc.ProductName)"
        Root="HKMU"/>
</Component>
Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
  • Hi Christopher, thanks for the reply. I tested out what you recommended, and indeed, if the key is already present then the preserved value is set as expected. However, I've noticed that this has the effect of making the key be created upon a clean install as a REG_SZ, which I obviously don't want to happen. Is there a way around this? Some way to create the initial key as a DWORD but then run a separate component to populate it with the preserved value perhaps? – Chris McAtackney Jan 21 '13 at 20:17
  • You can have a SetProperty custom action that sets the property to #1 if the property doesn't already have a value. This should help you prime the pump using just 1 component. – Christopher Painter Jan 21 '13 at 20:23
  • Ah my situation is a bit more involved as the registry entry in question is one which can be specified from the command line, but has a default in case the user leaves it out. I'll try experimenting with a few different configurations here to see which one produces the right result, but thanks for the pointers. – Chris McAtackney Jan 21 '13 at 21:28
  • I refer to this as property precedence. You will need more then one property to pull it off. Greatest -> Least: Value edited in UI, Value Passed at Command Line (if any), Value detected from previous installation (if any), Default Value (if any) – Christopher Painter Jan 21 '13 at 21:33
  • Yeah, it was originally all going into one property, but that just doesn't seem like it's ever going to work. I'll see how I get on using a couple of different properties. Cheers. – Chris McAtackney Jan 21 '13 at 22:31