0

The old version of the setup was created with InstallScope="PerMachine". The new version is intended to have InstallScope="PerUser"; it also needs to use the same registry keys as the old version creates.

The problem is that whatever values are stored under these registry keys during the upgrade will be overwritten at the end with the initial values stored by the old version. Even deleting these keys manually before the installation will make them reappear (with the wrong values) after the installation process.

I have tried creating a custom action and specifically delete these keys, but the result is the same.

How can I ensure that the old version does not interfere with the installation process of the new version allowing to delete the old Registry Keys and re-create them?

What I found to be working:

Performing a REPAIR immediately after installing the new version will yield the correct results!

Uninstalling the old version manually before installing the new one will not remove the keys, but will allow to overwrite them with the correct values.

PhilDW
  • 20,260
  • 1
  • 18
  • 28
Andy
  • 3,631
  • 2
  • 23
  • 32
  • I think you could get that repair happening auto-magically after the main install is done with a trick custom action after InstallFinalize. I have never tried it and don't want to recommend it. Please read my answer below first. – Stein Åsmul Dec 30 '17 at 19:44
  • As I said in my previous comment, I don't really want to recommend it, but you can try a custom action after InstallFinalize running a command line like this: ``msiexec.exe /fum [ProductCode] /qn``. This should silently kick off a repair of the setup you have just completed. Remove ``/qn`` to make it non-silent (for testing) - [msiexec.exe command line info](https://msdn.microsoft.com/en-us/library/windows/desktop/aa367988%28v=vs.85%29.aspx) - ``/f`` repairs the specified product, ``um`` rewrites user and machine registry keys. – Stein Åsmul Dec 30 '17 at 20:21
  • OK, I guess I should just remove the comments above, but I will leave them in for now. This approach does run and it works too, but only if you do it from the UI sequence (which means it will not run at all if your setup is installed silently). There are also many risks associated with improper conditioning which could exactly cause user data to be reset in the registry unexpectedly during upgrades for example. Not recommended at all. Please read the suggestions below instead for a more stable solution. – Stein Åsmul Dec 30 '17 at 21:05
  • @SteinÅsmul Scheduling the repair _After="InstallFinalize"_ does not work; msiexec will complain saying that _'Another program is being installed. Please wait until that installation is complete...'_ – Andy Dec 31 '17 at 09:36
  • Yes, it does work if you put the custom action at the end of the ``InstallUISequence`` (which shows the setup GUI), instead of the ``InstallExecuteSequence`` (which runs the actual installation transaction), but as I said then it won't run when your setup is installed silently - which is a serious problem. It is a very hacky thing to do, so don't use it. I just mentioned it as a last resort. – Stein Åsmul Dec 31 '17 at 12:23

2 Answers2

1

You should define what kind of upgrade you are doing, and if it's a major upgrade then where is it sequenced in your major upgrade element, although...

Probably the main issue is that cross context major upgrades aren't supported by Windows Installer, so if you are doing a major upgrade you will end up with both products installed. That's not an upgrade, that's most likely just a collision. So assuming that you want only one of them to be installed at the end of all this, you will need to uninstall the older per-machine installation and then install the per-user. As to why the uninstall of the per-machine product doesn't remove the registry keys, there are many possible reasons, such as they were created by the app not the MSI, or the component was marked permanent, or the component has another client product on the system - a log of the uninstall might show what's going on.

PhilDW
  • 20,260
  • 1
  • 18
  • 28
  • Very good point, but I thought this was an issue going the other way? I don't really remember properly. From per-user to per-machine install? Then you need to use a trick to be able to perform a major upgrade: [**Going from a per-user to a per-machine install during a major upgrade**](https://stackoverflow.com/questions/12110987/windows-installer-uninstalling-previous-version-when-the-versions-differ-in-in/12291807#12291807). That is for Installshield, but I guess it is possible to do the same in WiX if the issue is very important. – Stein Åsmul Dec 30 '17 at 19:50
  • The problem described in the question refers to switching from 'perMachine' to 'perUser', although I believe that the actual issue is that uninstalling the old version adds these keys back even if I delete them manually before the uninstall process. – Andy Dec 31 '17 at 07:57
  • It's not possible for an uninstalled product to self-repair, so I can only guess that the situation is not exactly as you believe Without knowing component ids of all the components in the feature (because repair goes to the feature level) and whether the ids were ever marked permanent or shared etc, there is not enough info. The repair will create an MsiInstaller entry (Application Event Log) and turning on MSI logging policy will create a log, and these should tell you exactly which product and component is being repaired. – PhilDW Dec 31 '17 at 19:30
  • @stein: The IS trick won't help. The problem is the behavior of the registry items that occurs even when the old product is uninstalled first. The failure of a cross-context upgrade just complicates the issue. The problem seems to be component id/sharing/repair issue. – PhilDW Dec 31 '17 at 19:37
1

I have to add this as an answer, too long as a comment. I will "evolve" it once you provide more information:

  • Why do you want to switch to per-user installation? In the MSI world this is not an ideal way to deploy. An application is usable per-user even if installed per machine. With a per-machine install you simply add the ability to write shared settings that should not be overridden by a user. And your application is easier to upgrade, uninstall, patch and manage overall.

  • Here are a few more links to explain some of the problems with per-user setups. They are real, I am only trying to warn people what problems they are most likely going to face (almost certainly going to face):

  • Are you deploying HKCU or HKLM keys? I would not recommend writing any HKCU values from your setup, they should be written by the application itself. A setup is for writing to HKLM and other places that require "elevated rights". It should never be used to write user preferences. There will be interference when you do upgrades (as you have experienced).

  • Where is the registry data you speak of stored? In a single MSI component or several? Is there anything else in that component that still needs to be installed without the registry keys? If you can, please add your source WiX file so we can see for sure.

I am sure that we can make all these problems go away if you follow our advice precisely. You are facing a very common MSI problem.

Let me attempt a tentative answer without having all the information:

  1. Remove all HKCU registry information from your setup (if you can).
  2. Update your application to write these HKCU values itself, and ideally write to a brand new location in the registry instead of the old one. For example HKCU\Software\MyCompany\MyApp\5 instead of HKCU\Software\MyCompany\MyApp. This "decouples" your old and new state, and you got room to maneuver and clean up things.
  3. Making your application write the HKCU keys is not a hack, but the right thing to do. It will make your application much more robust and generally easier to QA for yourself and your team. You can "wipe the slate clean" during testing and start over without a reinstall - in order to focus on application testing.
  4. Put any remaining HKLM settings in a single WiX component and set a good key path that will never be modified or deleted by the user or any other process. For example: HKLM\Software\MyCompany\MyApp\5\MyAppHKLMKeyPath = 1
  5. If you discover that you have to override a value for each user (in other words change something for every user in HKCU), you can do this with this approach which combines what the setup does with the application itself: http://forum.installsite.net/index.php?showtopic=21552 (if this is important, please read the whole, linked thread).
Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • I cannot make the application write the keys, because it's a plug-in, not a stand-alone executable; the registry keys are needed to register the module with the target application. All I want is to un-register the old version. I can do that by re-using or deleting the associated registry key. Neither works... – Andy Dec 31 '17 at 08:05
  • OK, I understand. It would be very helpful to see the source or at least the registry keys themselves to see what is going on. Is this for MS Office? Also, please do familiarize yourself with the perils of per-user setups by reading the links I provided above. They can be a nightmare. – Stein Åsmul Dec 31 '17 at 15:56