Unchanged files break patch uninstallation - wix

General Information:
We use WIX 3.10.3 to build both our Base Msi and Patch Msp.
Supports Windows Installer version 301
Patch is build using Purely Wix method as documented.
Root Cause for the issue:
Base Msi contained a file named "Sample.dll" with version as 1.0.0.0 and language as "neutral".
While building patch, WIX considered there was change to the contents of Sample.dll but the version is retained as "1.0.0.0" and language as "neutral".
Sample.dll used for Patch creation, even though there was no change to the contents but some how we were able to identify there was binary change when compared with the base and the msp dlls used for creation. Refer below screenshot from Beyond Compare
Beyond Compare Snapshot of the DLL's included for MSI and MSP
During installation of Base and then patch, as per Windows Installer File Versioning rules(https://msdn.microsoft.com/en-us/library/windows/desktop/aa368599(v=vs.85).aspx), the file "Sample.dll" was not re-installed by patch since the version and language are same.
Hence while removal of patch, windows installer requested the source of the msi.
This is causing uninstallation failures at our customers as the sources of the msi are not available during uninstall.
Here's a blog entry which said this issue is identified in Windows installer version 301 (https://blogs.msdn.microsoft.com/heaths/2007/06/28/unchanged-files-break-patch-uninstall).
We had already tried updating the installer version support to 405 in WIX and still the problem occurs.
Here the patch creation considers the Binary change between the base msi and patch msi to create the Msp whereas windows installer considers File versioning rules while installing.
Is there some changes that could help avoid such scenarios and how to ensure that only really changed files are considered for patch creation and installation?

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.

Wix:Disallowing installation of component: since the same component with higher versioned keyfile exists

I am doing a compatibility check of MSI in the OPS environment before deploying to Production environment.
A part of this i am deploying first the latest MSI say "MSIv2 to OPS environment on top of MSIv1 and the MSIv2 automatically uninstall the MSIv1 and install MSIv2 without any issues.
Now when i am installing MSIv1 on top of MSIv2. MSIv1 is installed and it is showing in control pannel as installed.But when i see the directory path no .dll files are there in the bin folder.
i am logging the action of MSI in log file which tell ...
Log:
Disallowing installation of component: {AC7BC9EB-4F1D-4FEE-B0C2-478966229D8E} since the same component with higher versioned keyfile exists
Forgive me for the long answer, but I think its important that you understand the basics:
Did you change the product code between the 2 MSI versions? My guess is that you haven't changed the product code between the 2 versions and windows installer is considering
this as a minor upgrade. First understand the difference between Major vs Minor upgrade.
Minor Upgrade
A minor upgrade is an update that makes changes to many resources. None of the changes can require changing the ProductCode. An update requires a major upgrade to change the
ProductCode. A minor upgrade can be used to add new features and components but cannot reorganize the feature-component tree. Minor upgrades provide product differentiation
without actually defining a different product. A typical minor upgrade includes all fixes in previous small updates combined into a patch. A minor upgrade is also commonly
referred to as a service pack (SP) update.
Major Upgrade
A major upgrade is a comprehensive update of a product that needs a change of the ProductCode Property. A typical major upgrade removes a previous version of an application
and installs a new version. A major upgrade can reorganize the feature component tree. During a major upgrade using Windows Installer, the installer searches the user's
computer for applications that are related to the pending upgrade, and when it detects one, it retrieves the version of the installed application from the system registry.
The installer then uses information in the upgrade database to determine whether to upgrade the installed application.
Now during Minor upgrade windows installer uses the following rules to replace existing files - Because unnecessary file copying slows an installation, the Windows Installer determines whether the component's key file is already installed before attempting to
install the files of any component. If the installer finds a file with the same name as the component's key file installed in the target location, it compares the version, date,
and language of the two key files and uses file versioning rules to determine whether to install the component provided by the package. If the installer determines it needs to
replace the component base upon the key file, then it uses the file versioning rules on each installed file to determine whether to replace the file.
At the core of any installer is the actual installation of files. Determining whether to install a file is a complex process. At the highest level, this determination depends on
whether the component to which a file belongs is marked for installation. Once determined that a file should be copied, the process is complicated if another file with the same
name exists in the target folder. In such situations, making the determination requires a set of rules involving the following properties:
Version
Date
Language
The installer only uses these rules when trying to install a file to a location that already contains a file with the same name. In this case, the Windows Installer uses
the following rules, all other things being equal, to determine whether to install.
Highest Version Wins—All other things being equal, the file with the highest version wins, even if the file on the computer has the highest version.
Versioned Files Win—A versioned file gets installed over a nonversioned file.
Favor Product Language—If the file being installed has a different language than the file on the computer, favor the file with the language that matches the product being
installed. Language-neutral files are treated as just another language so the product being installed is favored again.
Mismatched Multiple Languages—After factoring out any common languages between the file being installed and the file on the computer, any remaining languages are favored according
to what is needed by the product being installed.
Preserve Superset Languages—Preserve the file that supports multiple languages regardless of whether it is already on the computer or is being installed.
Nonversioned Files are User Data—If the Modified date is later than the Create date for the file on the computer, do not install the file because user customizations would be
deleted. If the Modified and Create dates are the same, install the file. If the Create date is later than the Modified date, the file is considered unmodified, install the file.
During a Minor Upgrade, the default file versioning rules can be overridden or modified by using the REINSTALLMODE property. The installer uses the file versioning rules specified by the
REINSTALLMODE property when installing, reinstalling, or repairing a file. The default value of the REINSTALLMODE property is "omus".
Now you have to decide whether you are going to do a MinorUpgrade or a Major Upgrade for your MSI. If it is a Major Upgrade, then by default the old version of the product is uninstalled
before installing the new version. Use the link "WIX MAJOR UPGRADE" below for more details on how to implement this. You can also set the below property
within the MajorUpgrade Element - to make sure that you can install an old version on top of the new version.
AllowDowngrades YesNoType When set to no (the default), products with lower version numbers are blocked from installing when a product with a higher version is installed;
the DowngradeErrorMessage attribute must also be specified. When set to yes, any version can be installed over any other version.
If you are sticking to a minor upgrade then, you will need to override the default file versioning rules using the REINSTALLMODE property as mentioned above and use the code "d"
d Reinstall if the file is missing or a different version is present.
Then use the following msiexec command:
msiexec.exe /i installer.msi REINSTALL=ALL REINSTALLMODE=vdmus
MINOR UPGRADE
MAJOR UPGRADE
MINOR UPGRADE - Replace Existing Rules
MINOR UPGRADE - File Versioning Rules
REINSTALLMODE
WIX MAJOR UPGRADE
Hope that helps!
The product code is "*" in wix.
MSI get the version from one of the exe, which is deployed as part of msi. The exe is install the service when MSI is installed.exe is versionsed so MSI will have the same version.
So when the lower version of MSI is installed the exe will also have the same version, hence exe compares with exe which is already there in the server and it decides not to install as the higher version already there.
So what I did is "RemoveExistingproduct" before="costing "
Which resolved the issue removing the product before the higher version.
Let me know if any other alternative is there and is it a right practice and what are the consequences.

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.