4

I am currently maintaining a piece of software that has loads of user defined registry keys. I'm trying to make a WIX installer that keeps these registry keys in tacted with the least amount of maintainability. I decided to make each value inside a registry key it's own component to allow me to use the NeverOverwrite='yes' feature of WIX. I assumed the existence of this would allow minor upgrades (ex. REINSTALL=ALL REINSTALLMODE=vomus) to create the value if it exists otherwise leave it alone. However this doesn't seem to be happening in my realworld example (No conditions on the feature) . The documentation is telling me I should be good. Here is a few samples:

<Product Id="UNIQUE_KEY" Name="Spotbox Manager" Language="1033" Version="1.0.1.0"    Manufacturer="Company"  UpgradeCode="MY_UPGRADE_KEY">
<Package  Platform="x64" Id="*" InstallerVersion="200" Compressed="yes"    InstallScope="perMachine" InstallPrivileges="elevated" />
<Upgrade Id="MY_UPGRADE_KEY">
  <UpgradeVersion OnlyDetect='yes' Property='SELFFOUND'
    Minimum='1.0.1' IncludeMinimum='yes'
    Maximum='1.0.1' IncludeMaximum='yes' />
  <UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
    Minimum='1.0.1' IncludeMinimum='no' />
</Upgrade>

This is the actual Fragments for the Registry Keys

<Component Id="cmp171812fcc51a4b91ad386fa8c27c9b89" Directory="TARGETDIR" Guid="COMPONENT_GUID"  Win64='yes' NeverOverwrite='yes'>
  <RegistryKey Key="SOFTWARE\Company" Root="HKLM">
    <RegistryValue Name="Value" Value="1100797834" Type="integer" KeyPath='yes'/>
  </RegistryKey>
</Component>
<Component Id="cmp211639bff9694f029028a22cb0bb9687" Directory="TARGETDIR" Guid="NEW COMPONENT GUID"  Win64='yes' NeverOverwrite='yes'>
  <RegistryKey Key="SOFTWARE\Company" Root="HKLM">
    <RegistryValue Name="Country Code" Value="1" Type="integer" KeyPath='yes' />
  </RegistryKey>
</Component> ...

Please Note: The Key is the same for both values This still seems to blow away the user's value when I try and change it.

  • How exactly are you setting the GUIDs? And, try enabling Permanent beside NeverOverwrite. – Jirka Hanika Mar 22 '13 at 20:47
  • I'm receiving the guids from Resharpers nguid snippet command. I don't see how the Permanant would matter. Do i use it with NeverOverwrite or instead of? – Gregory Coburn Mar 22 '13 at 21:32
  • With. And if I knew why (in your case), it would be an answer, not a comment. – Jirka Hanika Mar 22 '13 at 21:34
  • Still doesn't seem to have any affect on it. I'm wondering if it is any settings. If it doesn't work on a particular arch or something like that. – Gregory Coburn Mar 22 '13 at 21:43
  • I think I made it out. Yes, the Permanent should do it, but that needs to be set on the *old* MSI as well. The reason is that the component undergoes uninstallation via the old MSI. This results in the KeyPath disappearing. That triggers installation by the new MSI. – Jirka Hanika Mar 22 '13 at 22:13
  • Uninstalling only happens in major upgrades and not minor upgrades (Only changing the version number). I'll try it and let you know. Thanks for the assistance. – Gregory Coburn Mar 22 '13 at 22:41
  • I've setup a sample project with a simple registry and it worked! (NOTE: on a different computer) i ran verbose logging to see what the logs say and I received: Disallowing installation of component: MainRegistry2 since the registry keypath exists and the component is marked to never overwrite existing installations. (essentially same code). During CostFinalize phase. – Gregory Coburn Mar 23 '13 at 00:17

2 Answers2

1

First, there is no problem with having multiple values under the same registry key, and using them as separate keypaths. The term "keypath" has nothing to do with registry terminology, and in case of registry, it actually must identify a value and not a key.

Second, your comments mention that product uninstallation does not happen during a minor upgrade. This is correct on product level, but not on component level.

You should check that you have not changed the GUID or keypath of the misbehaving component between the old and the new version of your product - if you did, you clearly broke the rules for a minor upgrade (component removal). However, read on even if your GUIDs are stable, I have a more generic explanation for you.

Minor update is a reinstall. I am imagining the following order of events.

  1. (CostFinalize) Windows Installer checks that the same component as per keypath is already installed (not rewritten or deleted by the user) and therefore does not have to be installed; as per NeverOverwrite being enabled).
  2. (InstallExecute) Windows Installer uninstalls the component from the old MSI, because the component will be replaced by the new MSI (as guaranteed by minor update rules); as per Permanent being disabled in the old package.
  3. (InstallExecute) Windows Installer remembers the check from Step 1 and does not care about installing the different component with the same keypath.

You have at least these options for correction, pick one.

  • Go with a major upgrade. This is almost always the easier and better choice.
  • Enable Permanent in addition to NeverOverwrite, assuming you can do so in all releases; basically, that you did not release anything definitive yet. Most people keep these attributes in sync so why not follow the crowd and have fewer issues.
  • Mess with the order of actions. Example:

    <RemoveExistingProducts After="InstallValidate"/>

This last option will make your upgrade slower, but that is probably necessary if you really want minor upgrades and take advantage of NeverOverwrite without Permanent.

Jirka Hanika
  • 13,301
  • 3
  • 46
  • 75
  • I'm going to try and run processmonitor tomorrow and see if there is any removal then adding of the key or if it is just overwriting it. I'll also keep the permanent on it. I am lucky in the fact that it has not ever been deployed out in production yet, so i have some time to get it the way i want it. – Gregory Coburn Mar 25 '13 at 08:30
0

I found the issue it was a user error I had so many values in the registry that I didn't notice another section that was similar but without the component elements (Old configuration). After I removed it everything worked as expected. Thanks for the help guys.