3

We have developed an application that is distributed through Windows Installer, created with the use of WiX, where our customers can upgrade from any older version to the newest.

Our latest version however, deletes 2 dll's, and this is only rectified through a reinstall.

Details on the NuGet packages

Microsoft.IdentityModel.Protocol.Extensions was upgraded from Nuget Version 1.0.2.206221351 and File version 1.0.20622.1351 to Nuget version 1.0.4.403061554 and File version 1.0.4.54.

Similar changes happened to file versioning of System.IdentityModel.Tokens.Jwt from Nuget version 4.0.2.206221351 to Nuget version 4.0.4.403061554.

So by changing how the File version was calculated, MS effectively changed the version to a downgrade of the previous (from 20622 to 4 on the build version).

Why the dll's are removed on upgrade

Some call it a bug, and some call it a feature, but what happens, is that the MSI has a step where it records all the files that needs to be upgraded, it then uninstalls the current version, and then only installs the files that was unchanged or bumped in version - any downgrades are left out.

Question: How do we get around it?

We are shipping this product to a lot of different customers, with very varied technical skills, so an upgrade better work, or we will be flooded with support issues. Are there anything I can change, without actually disabling features like the ability for the MSI to rollback in case of errors, which I have seen as a trade off for others solving the same issue.

Squazz
  • 3,912
  • 7
  • 38
  • 62
Johny Skovdal
  • 2,038
  • 1
  • 20
  • 36

2 Answers2

5

You have a few options. One is to change where you schedule RemoveExistingProducts. Another is to use REINSTALLMODE=AMUS instead of the default OMUS. Another is to do version lying on the offending DLLs so that they always get reinstalled. (Author the file element so the version is 65535.0.0.0 or something like that.)

It's an MSI feature... the bug is in Nuget releasing a newer DLL with a lower version #. That breaks MSI's component rules and default file versioning rules.

Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
  • I'm a new maintainer on our installers, so I actually don't know why we use OMUS. Any caveats on the change? Version lying sounds like an option too, but how do I do that? I've only found hints on how to do it, but couldn't make it work. Will I have to do version lying for all files for it to work? As for it being a feature, I still don't get why uninstalling downgrades is an outcome you would want? – Johny Skovdal Nov 07 '17 at 18:57
  • OMUS is the default "safe" choice. If you have shared files in places like SystemFolder, WindowsFolder, CommonFilesFolder, OMUS is for you. If all of your files are in your own ProgramFilesFolder\Company\Product then AMUS can be OK although upgrades will take longer to run. You don't need to version lie any files if you do AMUS. If you do OMUS you only have to lie the problematic files. – Christopher Painter Nov 07 '17 at 19:04
  • REINSTALLMODE=AMUS did the trick! Thanks! For our bootstrapper, we added `` to the MsiPackage with the problem. As for version lying I never found a way for that to work, which might have been an even better solution. – Johny Skovdal Nov 10 '17 at 10:29
  • A = "Force all files to be reinstalled, regardless of checksum or version." https://msdn.microsoft.com/en-us/library/windows/desktop/aa371182%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 – Nickolai Nielsen Nov 10 '17 at 12:04
  • Another thought occurred to me today. Can you deploy the DLL to another directory and still load it in your .NET application? If so it would be a new component and you would side step this whole problem. – Christopher Painter Nov 13 '17 at 02:07
  • It could be done yes, but it is used for multiple exe's, and would have to be maintained for them all, so I'd rather not go that way. Nice idea though. :) – Johny Skovdal Nov 13 '17 at 08:30
  • I'd think copy/paste into a few app.config would be easy. I'm not sure what there is to maintain once you've committed the changes. I think it's a pretty good option to get you out of jail. – Christopher Painter Nov 13 '17 at 13:28
1

This might help:

https://blogs.msdn.microsoft.com/astebner/2015/11/16/why-windows-installer-removes-files-during-a-major-upgrade-if-they-go-backwards-in-version-numbers/

and basically Chris is correct, and:

  1. The RemoveExistingProducts placement should be before the costing actions which cause the error.

  2. Another alternative is to open the files with Visual Studio and alter the file versions in the resources so that the rules are followed. File version would not affect assembly version. Just run Visual Studio, then File-Open File, and the Resources section will show where you can change the version.

  3. It's also very likely that a repair will restore the missing files because the missing files "break" the product install. That's easy to test. If that is really the case, then it will repair automatically (and just once) if the app starts with a shortcut, or you can arrange for the shortcut to be advertised. If not, I've seen people use MsiProvideComponent () to make sure the files exist because that will do the repair/install.

PhilDW
  • 20,260
  • 1
  • 18
  • 28
  • Doesn't option 1 break rollback as a commenter suggested? (https://blogs.msdn.microsoft.com/astebner/2015/11/16/why-windows-installer-removes-files-during-a-major-upgrade-if-they-go-backwards-in-version-numbers/#comment-21771). As for option 2, what do you mean exactly? I do not have the source, and opening the file in Visual Studio, only opens up the Object Browser for me? But changing the file version actually might do the trick (found another way here https://stackoverflow.com/questions/284258/how-do-i-set-the-version-information-for-an-existing-exe-dll). Will try it out. – Johny Skovdal Nov 07 '17 at 18:51
  • #2 would be a problem because typically nuget assemblies aren't stored in source control. Typically you go a nuget package restore during the build which downloads the files again. So now you'd have to have version resource hacking backed into your build automation. :( – Christopher Painter Nov 07 '17 at 19:05
  • Rollback could be an issue, but so is adding REP after InstallFinalize, and that's even a documented choice with a vague caveat! But the point is about the choices available, and what works best in the situation. – PhilDW Nov 07 '17 at 22:10
  • As mentioned, 1) would break restore, so we sought other solutions. 2) was not an option for us because of strong naming. Option 3) might work with MsiProvideComponent, though I do not know what that is. It didn't restore on it's own though. It is a windows service, so I don't know if that is way it does not repair automatically? Thanks for the input though, helped med narrow things down! :) – Johny Skovdal Nov 10 '17 at 10:32