"Downgraded" MS dll disappears on upgrade - Windows Installer - wix

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.

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.

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:
The RemoveExistingProducts placement should be before the costing actions which cause the error.
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.
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.

Related

WiX HowTo: Downgrade a third-party dependency without re-installing?

Background
WiX & the Windows Installer are completely new to me.
In production, we used an MSI (created using WiX) to install our software. The MSI references a third-party assembly (e.g. OtherCompany.ThirdParty.dll, version 2.5).
The next release of our software must reference an older version of the third-party assembly (e.g. OtherCompany.ThirdParty.dll, version 1.7).
While I understand that installing an older version of a dependency is uncommon, it must happen.
So my question is... how do you configure a MSI (generated by WiX) to use an older version of an assembly without having to completely uninstall the existing package?
Options
We have explored the following:
Increment the assembly's version
it's a third party assembly, and
for traceability this is not an option
rename the assembly
the dependency is being retrieved using NuGet... so this won't be straight forward
force existing install to be completely removed (automatically or manually)
we don't want configuration information that was collected during the previous installation to be lost, so this isn't an option
schedule RemoveExistingProducts before costing
not recommended by Microsoft (see: MSDN)
custom action: to delete dependency
if the installation fails, the application may be left in an undefined state
override file version in setup
moving forward, this will be error prone
changing the REINSTALLMODE
From the articles that I have read, it appears that this should only be used as a last resort.
use a WIX companion file
am still investigating
For Moderators
I am aware that there are other SO posts on this subject. Please note that several of the recommended solutions are incomplete or are error prone.
References
MSDN: Patching and Upgrades
MSDN: RemoveExistingProducts Action
downgrade a library during a msi upgrade
Why Windows Installer removes files during a major upgrade if they go backwards in version numbers
MSI Writing Guidelines
What Every Developer Should Know About MSI Components
Windows installer deletes versioned file during product upgrade, instead of downgrading it
MSDN: Windows Installer - File Versioning Rules
Msiexec REINSTALL=ALL REINSTALLMODE=vamus not reinstalling anything
good overview of what is happening under-the-hood
Forcing an upgrade of a file that is modified during its initial installation
this is an older post is from 2009
Some issues are best solved by the application design rather the deployment.
There are two places to save a particular version of a .NET assembly: the GAC or the application folder (or subfolder with probing privatePath). In either case, you might want to use a bindingRedirect.
Also, you can load from a specific location using AppDomain.AssemblyResolve, provided the binding is not successful using the GAC.
General Reference: How the Runtime Locates Assemblies—thanks to #Pressacco.

Visual studio setup project update or patch certain dll files

I have a Visual studio 2010 project A and a setup project SetupProject.
I would like to have a solution of patching/upgrading the installation on one machine by updating several dll, namely a.dll (primary output of A) and b.dll (some other dlls that A depends on).
Following this patching guide using Orca and msimsp, I am able to create a patch solution for my installer.
The problem is msimsp needs a target for comparing with the newer installer, meaning I have to say specifically "this is a patch from 1.0.1 to 1.0.2" and this patch requires that the current installed version is 1.0.1. I cannot use that for patching a 1.0.0 installation.
In other words, the patches have to be applied in sequence, one after another.
My question are :
How can I use Patch_101_To_102 to upgrade any version 1.0.x to a 1.0.2 installation, without the need to go through 1.0.1 patch ?
Would you suggest another solution other than this patching solution ? The problem with this solution is that it calculates the delta difference between two version, so I think that's why it requires the patches to be applied sequentially. It would be great to have a solution saying "overwrite these specific dlls only"
Strictly speaking Visual Stusio suports only the RemovePreviousVersions upgrade, so most people in your position might choose another tool that has a bit more support for patching.
Anyway, why are you creating a patch for 1.0.1 to 1.0.2? Most people build an accumulating patch. Just keep the 1.0.0 build around for as long as you need it, and build all your patches against an MSI that keeps accumulating fixes. Youd increment your MSI version, create a new patch guid, and in the PCP file say that this new patch superseded the previous ones, in ListOfPatchGUIDsToReplace.

Wix major upgrade, replace files regardless of newer file version

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?
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. :)
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.

How to include files that changed but have the same version number into MSP using WiX Pyro?

I created an MSP patch file using WiX Pyro(using purely WiX toolset). But it seems that created MSP file doesn't include files changed in content but not changed in version number. As I think, most of those files are not actually changed in main content but just rebuilt by Visual Studio. So, it may be desirable behavior that Pyro does.
But my customer asked me why files installed by the latest MSI and files updated by MSP patch are different. So, I want to know there is any way to include those files into MSP patch, or can I tell my customer that those two file sets(the latest MSI, old MSI + MSP) are the same so you can use the product safely? (Of course, I think my file version management is pretty poor and not systematic, but MSI's version rules feel too strict and somewhat inflexible to me.)
The Windows Installer file update rules are what they are, and I don't think you're going to get them changed. The standard rule is that you tell Windows the file is updated by incrementing the version, and then at install time a higher version will replace a lower version. That's the reason tools that generate patches also use the version rule - why should they include files that haven't got a higher version? Service packs, patches, hotfixes etc all work based on file versions.
If you want to use whatever file versions you like, then stop using patches and do a major upgrade that does a RemoveExistingProducts early so you get the equivalent of an uninstall of all the old files followed by an install of all the new ones.
By the way, if these are managed code files and you believe that incremnting the file version means incrementing the assemblyversion, then use AssemblyFileVersion to increment the file version and leave assembly version alone.

MSI Installation issue

I am having an MSI file which copies a set of dll from it source to destination folder. While running the MSI the dll are copied to the destination folder also the MSI is installed in the system. I can see that in ADD or REMOVE programs.
Whenever there is a change in dll, i copying the new dll and building the MSI again. When i tries to run MSI in the same system i am getting error "Another version is already. Uninstall that version and proceed" something like that.
What i am doing until now is uninstalling the old one (MSI) and installing the new one.
But i want the MSI to update the older dll with the latest dll from the MSI instead of uninstalling and installing again.
Thanks in advance.
You can't just rerun the MSI to do an update. There's some background here, even if you are not using Visual Studio setups, and it's still relevant after all this time:
https://www.simple-talk.com/dotnet/visual-studio/updates-to-setup-projects/
To replace a single file, build a patch, an msp file. To upgrade the entire setup, including that Dll then use the WiX majorupgrade element, and that may be a lot easier than building a patch, especially if your setup is small and doesn't take long to install. Increase the file version of the Dll to make sure it gets replaced.
welcome to StackOverflow - it seems to be your first post. I would read this thread if I were you to get an overview of how to implement a WIX major upgrade: How to implement WiX installer upgrade?. Here is another thread (didn't read this one through): How to get WiX major upgrade working?
A major upgrade is essentially an automatic uninstall of the existing version and reinstall of a new version. This is the least error prone update mechanism in Windows Installer. It is the recommended approach to try at first - it works well. A minor upgrade - which is upgrading the existing install, is generally more difficult to get right in the beginning. A number of technical restrictions apply. Here is a very good summary of what is required for a minor upgrade to work (as well as other details): http://www.installsite.org/pages/en/msi/updates.htm
Check out this well known wix tutorial for upgrades and patches. And MSDN.