Wix major upgrade, replace files regardless of newer file version
Asked Answered
S

2

10

My WiX installer (Wix 3.10, MSI 4.5) uses MajorUpgrade for updating. The files to be installed are harvested with heat.exe in pre-build. The current (older) msi file contains a file nlog.dll (which came with a NuGet package v4.1.0) that has a file version of 4.1.0.0, a product version of 4.1.0 and last write time of 2015-09-01.

Since the nlog team ran into some strong naming issues, they published an updated NuGet package v4.1.1, containing an updated nlog.dll with its file version decreased back to 4.0.0.0 while its product version has been increased to 4.1.1, last write time is 2015-09-14.

Now I'm running into a related issue as Robbie did here: wix major upgrade not installing all files: When I install the new msi package and the major upgrade is performed, the present nlog.dll (which is newer according to its file version, but older according to its file date and product version) is being removed, but the new nlog.dll isn't installed.

However, using Schedule="afterInstallExecute" or Schedule="afterInstallFinalize" as suggested won't do the trick for me. Instead of removing the newer file and not installing the older one as in Robbie's case, it doesn't overwrite the present file, and just leaves it in place.

Long story short, I would like my installer to simply install all files that come with it, regardless of any file/product/assembly versioning stuff. There are valid circumstances in which replacing a newer file with an older one is desired. Can't you just tell the installer engine to ignore file versions/dates? If not, what are my options?

Stenopetalous answered 16/9, 2015 at 8:26 Comment(1)
We 'fixed' this by installing all of our applications in a path that includes the version number as a path. That way all parts of the application will be installed in a fresh location and thus not get these problems. Unity 3D is another offender that does not care about properly versioned dlls.Readymade
S
11

You can set the REINSTALLMODE property to AMUS instead of OMUS. This will affect all components globally.

The other trick is to use "version lying". This is where you author the file element with a higher version. Using heat can make this difficult as now you have to transform the XML before compiling it.

Of course the real solution is to hit the nlog team over the head. But based on what I've seen from them over the years it'll never happen. Perhaps you just use a resource editor to hack the DLL and 'fix' the version #. That's assuming you don't need it strong named. This feels dirty and a possible CM nightmare to me though.

Or just dump nlog. :)

Steve answered 16/9, 2015 at 11:21 Comment(4)
Setting <Property Id="REINSTALLMODE" Value="amus" /> inside the <Product /> node actually works. Since I don't install any shared components that might be downgraded accidentially (see James' comment here: https://mcmap.net/q/104551/-windows-installer-deletes-versioned-file-during-product-upgrade-instead-of-downgrading-it), I think I can use that solution.Stenopetalous
I had previously considered "version lying" as you suggested, but it is not a viable option, for the reason you pointed out. Dumping nlog or modifying the dll is a too narrow solution imo, since this might not be an option in other similar cases. Thank you very much for your input.Stenopetalous
Personally I'm not a fan of heat for reasons documented here blog.iswix.com/2007/06/…Steve
BTW, I don't consider it too narrow a case. I consider it a solution to a problem that shouldn't exist. Someone else did the wrong thing and now it's causing you a problem that shouldn't exist.Steve
C
0

If this is a major upgrade and you want everything to be uninstalled before the new product is installed, then you schedule RemoveExistingProducts after InstallInitialize or InstallValidate. That does the uninstall first.

I can't tell if you're getting the "disallowing install..." issue or not, but if you are, and there are other clients of the Dll (it's shared with other installed products) then I'd see if that Dll has support for private copies so you can have you own private copy for your product. If it is shared with other products I wouldn't use version lying - I'd open the Dll with Visual Studio "open as file" and change the version! Make that your latest shared version, so every package that installs it can just use it.

If it's not shared with other products and you're just running into that MSI quirk, then make your own upgrade element and schedule RemoveExistingProducts before CostInitialize, which is what is deciding not to install. That works, but it's before MigrateFeatureStates so you will lose feature migration in your major upgrade.

Cacie answered 16/9, 2015 at 17:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.