Recently I released a package versioned 0.8.3 and I'm ready to release a new package now. I was, however, struggling to implement a Major Upgrade / Upgrade. It seemed like the WIX_UPGRADE_DETECTED variable was never populated.
Then I ran across WiX3 major upgrade not working where the accepted answer states that:
All setup versions (again, not file versions) must be 1.0 or greater.
And indeed temporarily bumping the major version of both packages to 1 seemed to fix the issue. However I can't retroactively change the version of the old package as it is already installed on thousands of computers.
What is the best way to cleanly uninstall the old package while installing the new one? Is there a better way than setting up a CustomAction that runs msiexec.exe /x {PRODUCT-CODE}?
As long as your upgrade code is stable between releases, you just need the upgrade table properly authored to be inclusive of the version you want to upgrade.
What construct do you use to implement your major upgrade? Do you use the MajorUpgrade element? It should pretty much work straight out of the box:
<MajorUpgrade Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."
AllowDowngrades="no" AllowSameVersionUpgrades="no" />
Perhaps you are using old-style major upgrade elements: How to implement WiX installer upgrade?.
You should provide us with your WiX snippet that you use to implement major upgrades.
I would make sure that the max version specified in your Upgrade table is the same as the setup version you are currently installing.
Some Links:
Answers:
Bob Arnson, WiX Developer's blog on major upgrades: https://www.joyofsetup.com/2010/01/16/major-upgrades-now-easier-than-ever/
Larger sample with old-style major upgrade elements: Doing Major Upgrade in Wix creates 2 entries in Add/Remove Programs
How to implement WiX installer upgrade?
Documentation:
http://wixtoolset.org/documentation/manual/v3/howtos/updates/major_upgrade.html
https://www.firegiant.com/wix/tutorial/upgrades-and-modularization/
Related
After some googling I came up with a configuration that should allow me to install only newer versions of my package (which it does) while replacing the older, already installed version(s) (which it doesn't)
My wxs file is as follows:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="Gdml File Viewer" Language="1033"
UpgradeCode="5fb07c15-32a5-4b8a-9794-e4425bfc2eea"
...>
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine" Platform="x64" />
<MajorUpgrade Schedule="afterInstallValidate"
DowngradeErrorMessage="A later version of [ProductName] is already installed"
AllowSameVersionUpgrades="no"
AllowDowngrades="no" />
...
As expected it does allow me to install newer versions, but the older version is not uninstalled. It still shows up in the "Apps & features" list:
(The other instance has version 2019.14.181.35181)
Logging: To properly debug a failed major upgrade you need to create a proper log file (various ways to create log file - also by policy).
msiexec.exe /i C:\Path\Your.msi /L*v C:\Your.log
Auto-logging could be on: check the TEMP folder for any auto-generated log files there. If not, run again on a virtual to reproduce the upgrade problem with logging enabled.
Failed Major Upgrade: When you see two entries in Add / Remove Programs your major upgrade has failed (generally). You need to fix the configuration of the Upgrade table. See likely causes listed below.
Minimal WiX Markup: The minimal WiX markup for a default upgrade table - with normal parameters (which works fine, see below with screenshot) - is just:
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
Advanced: It is even possible to combine the above "convenience element" for simple major upgrade configuration with old-style elements for total control of Upgrade table content. Samples here.
On Major Upgrades: MajorUpgrade and Upgrade elements. How to use them:
How to avoid having two versions of a product installed with Windows Installer / MSI?
Adding entries to MSI UpgradeTable to remove related products
Likely Causes: A short summary of some of many possible causes for failed major upgrades.
Mismatched Upgrade Code: There might be a mismatch in the upgrade codes between the old and the new version of the MSI so the products are not identified as related. This should leave two versions installed afterwards (uninstall of old version never happened).
Missing Upgrade Code: Just adding that it is possible for the upgrade code to be missing from the Product element. This is generally an error, unless you want to do something specifically weird.
Missing MajorUpgrade Element: The whole Major Upgrade element can be missing and no Upgrade element present. The latter is for manual configuration of major upgrades, the former for "auto-magical" implementation of typical major upgrade scenarios. Sort of "best practice".
ProductVersion: There might not have been a bump up of one or more of the first 3 digits in the product version (fourth field ignored).
Product Code: As a side-note you might get a warning that the product is already installed, this means the product code has NOT changed (which it should for a major upgrade).
Dangling Version: It is also possible that your WiX markup is fine, and you have a dangling older version that was never correctly configured, if so uninstall it manually and try again or try on a clean virtual. If you auto-generate the product GUID you can end up with several versions of your product installed at once if the major upgrade isn't set up properly.
Installation Context: MSI files can install per-user or per-machine. If you have an installation per-user and then run a per-machine installation it will not detect the previous version. Do you have any hard coded references to ALLUSERS in your package?
SecureCustomProperties: Quickly - while I remember - in secure environments (corporate environments with users running without admin rights) you need to add the ACTION property from the Upgrade table to the list of secure properties (properties allowed to be passed to deferred mode).
Package Code: A very special case I have seen is when the new package has the same package code as the old one (or an existing installed package). This is an extreme design error and must not occur. Always auto-generate the package code, it is the right way to do things. Windows Installer will treat the two packages as identical by definition (as opposed to actual fact - you won't believe the X-Files that can result).
Further Details: Some further things to remember:
A major upgrade is essentially an uninstall of the older version and an installation of the new version with a number of scheduling options for the order in which actions take place (install new first, then uninstall old or vice versa).
As stated above you could also have a straggling older version of a setup on the box that wasn't properly configured or some X-Files nonsense happened that causes it to fail upgrade. Happens.
Unlikely with WiX, but it is possible for the standard action RemoveExistingProducts to be missing from the InstallExecuteSequence.
WiX Learning Curve: Suggest using some samples to help speed up the learning process. The only thing that really helps? Here are some WiX Quick Start Suggestions. There are sample links in there.
Minimal WiX Sample: There is this old sample: Transparent Aluminum. Essentially a walk-through of how to use Votive to create a WiX-based installer. It includes a major upgrade element. I believe this simple configuration adds the protection against downgrade that you seek:
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
See the Upgrade table that results:
Test Case: Using the Transparent Aluminum as test project, you can try this procedure to make the upgrade work:
Set the product code to * in order to auto-generate a new ProductCode for every build ("<Product Id="*" ...").
Compile the first version of your MSI. Right click WiX project in solution view in Visual Studio and select Open Folder in File Explorer. Into bin and Debug or Release.
Rename the compiled MSI by adding _1 to the end of the file name. For example: MySetup_1.msi
Now bump up one of the first 3 digits of the product version field in the WiX source: <Product Id="*" ... Version="2.0.0"
Compile a new MSI and rename it: MySetup_2.msi
Install the MSI files starting with version 1 and then the second one. Verify that major upgrade succeeded.
Advanced: Here is a demo of an advanced way to configure major upgrades using a combination of the convenience element "MajorUpgrade" and the older "Upgrade" elements (that allow you more fine-grained control of the resulting Upgrade table):
Adding entries to MSI UpgradeTable to remove related products
And here is a sample of using only the older Upgrade elements resulting in more work, but total control of the Upgrade table: Major Upgrade - "The Old, Manual Way".
Links:
Doing Major Upgrade in Wix creates 2 entries in Add/Remove Programs
Upgrading a WiX generated package with major version zero
Unable to remove previous versions of MSI. Multiple entry's show up in control panel
Adding entries to MSI UpgradeTable to remove related products
This problem, in fact, is to avoid a problem I will not solve
When I install my product once and I use the MSI again, the unloading process is performed.
However, this does not remove residual information from the registry, which must be cleaned Up using "Windows Installer Clean Up", and when reinstalled, a registry permission issue occurs.
I saw the Checking for Oldies, However, it was found that FindRelatedProducts only performed on the first installation, that is, when I installed the MSI again, FindRelatedProducts did not.
<Upgrade Id='YOURGUID-7349-453F-94F6-BCB5110BA4FD'>
<UpgradeVersion OnlyDetect='yes' Property='SELFFOUND'
Minimum='1.0.1' IncludeMinimum='yes'
Maximum='1.0.1' IncludeMaximum='yes' />
<UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
Minimum='1.0.1' IncludeMinimum='no' />
</Upgrade>
<CustomAction Id='AlreadyUpdated' Error='Foobar 1.0 has already been updated to 1.0.1 or newer.' />
<InstallExecuteSequence>
<Custom Action='AlreadyUpdated' After='FindRelatedProducts'>SELFFOUND</Custom>
<Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND</Custom>
</InstallExecuteSequence>
So I'd like to ask you guys
How do I check every time I run MSI when I have installed it? Is it installed and the same version, If the same version has been installed, exit the installation process.
When you run the "same" MSI again it goes into maintenance mode, often just a repair. Windows doesn't even need to use the MSI you use for this "install" because it uses the original MSI for the install, which may or may not be the one you attempt to install again. So it's not clear what you mean by "the unloading process" or what you expect running the same MSI to actually do.
FindRelatedProducts is for major upgrades, but that means incrementing the ProductVersion and changing the ProductCode. Running the same MSI does not cause a major upgrade (see WiX MajorUpgrade element).
So again, what are you expecting to happen when you run that same MSI again? It seems that you are not uninstalling it, so it will go into maintenance mode using the original MSI file, so there is nothing you can do to change that behavior because it's embedded in the installed product's MSI. Since you are apparently not uninstalling the installed product, it won't remove its registry entries. You should say what those residual registry entries are and why they are residual if in fact the product is not being uninstalled.
MSI Zapping: I am not sure what exactly you have done - you seem to have zapped your installed MSI - which is not recommended at all. It can cause serious problems - up to and including total MSI database corruption in the registry.
However, first things first:
MajorUpgrade Element: You can use the more convenient MajorUpgrade Element instead of the older-style elements you are using. Here are the older-Style Upgrade Elements in use. Directly below is a sample of the more modern, MajorUpgrade convenience element in action:
<MajorUpgrade Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."
AllowDowngrades="no" AllowSameVersionUpgrades="no" />
Maybe try this element instead of those you are using. Just comment the old ones out and replace with this simple element. If you do this correctly your major upgrade should work "out of the box". Make sure you specify an UpgradeCode in the Product Element. See the documentation for major upgrades
Relevant Links:
How to implement WiX installer upgrade?
Upgrading a WiX generated package with major version zero
How to implement WiX installer upgrade?
I did not fully understand this section of your question: "When I install my product once and I use the MSI again, the unloading process is performed. However, this does not remove residual information from the registry, which must be cleaned Up using "Windows Installer Clean Up", and when reinstalled, a registry permission issue occurs".
Zapping: What exactly did you do? Zap the installation? Why? You should be able to successfully uninstall from Add / Remove programs? Did that uninstall fail? What is the error message on reinstall?
Modify / Repair: MSI will detect when it is already installed in the same version auto-magically. You will then see the setup's modify / repair dialog show up, and not the first time installation dialogs.
These modify dialogs only show up if you double click the original MSI files used to install, without rebuilding it. Or you invoke modify from Add / Remove Programs.
If you rebuild your setup, it will have a new package GUID at the very least, and MSI will then detect that the freshly built MSI is not the one that is already installed, and an error message shows up. Now you can uninstall the current version from Add / Remove programs.
Related Products: An MSI will also detect if there are related versions installed if you correctly author the Upgrade table - as you seem to do.
If you generate a new product GUID each time you compile, you will be able to install the new version "on top of" or "side-by-side" with the older installation, unless you author the upgrade table - in which case the older version should be automatically uninstalled as part of the new version's install.
You need to understand package code, product code and upgrade code. The package code is auto-generated for every compile and build. The product code you can set to auto-generate by setting it to * in the product element, or you can hard code it and change it as required. The upgrade code should stay the same once defined. Please google the difference between these different codes - I don't have time to wrap up this explanation right now.
I have a project with a lot of MSIs (installed with a bootstrapper). Recently, after a major upgrade, I noticed that the previous version wasn't being uninstalled in Programs and Features (Win 7). That is, after upgrading from Version 1 to Version 2, both Version 1 and Version 2 are in Programs and Features.
This is a common problem, but it's a problem with a lot of different shades of grey -- I have an uncommon shade of this problem.
The problem may lie in a specific MSI. This MSI can only run during the initial install. Therefore I never change its version number. Here is what it looks like (to show that it's a legit Major Upgrade):
<Product Id="*"
Name="MSI"
Language="1033"
Version="1.0.0.0"
Manufacturer="Bob"
UpgradeCode="GUID-HERE">
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<FeatureRef Id="ReferenceToFeature"/>
</Product>
Here's why I think this is the MSI that's causing the problem: when I run the major upgrade, I have Version 1 and Version 2 in Programs and Features. When I run the uninstaller with verbose log, I can see that it uninstalls all of the MSIs, in that I get the boostrapper uninstall log file, then I get separate uninstall log files for the rest of the MSIs.
If I look at the log file for this MSI, I noticed a problem. Here's the part of the log file that I think may be the problem:
...
PROPERTY CHANGE: Adding INSTALLLEVEL property. It's value is '1'.
Disallowing uninstallation of component: {GUID-HERE} since another client exists
Disallowing uninstallation of component: {GUID-HERE} since another client exists
...
I recognize the GUIDs. They are GUIDs for components in my MSI. I know that this means that another program is using the resource -- that's why it won't uninstall -- but for the life of me I can't think of what program that would be! I'm installing on a clean virtual machine, and the program that my installer installs isn't running when I uninstall!
Some more info that makes me think that this MSI is causing the Programs and Features doubling-up: after I uninstall Version 2, I'm left, of course, with Version 1. When I uninstall Version 1 with verbose logging, the only log for an MSI that pops up is for the MSI in question! No other MSIs are uninstalled during that uninstallation.
I've tried adding the attribute AllowSameVersionUpgrade="yes" to the element to the MSI -- this
<MajorUpgrade AllowSameVersionUpgrade="yes"
DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
-- and that actually breaks my installer, because it makes the MSI install during the update installation, where I only want the MSI to install during the initial installation. It also doesn't fix the problem, in that both version still show up in Programs and Features.
However, it does cause the MSI to be uninstalled the first time through. That is, before, when I didn't put in the AllowSameVersionUpgrade="yes" attribute, the MSI wouldn't successfully uninstall during Version 2 uninstallation, and then when I uninstalled Version 1 I would get a log file uninstalling it. When I add the attribute, I still get the doubled up versions in Programs and Features, except this time I can uninstall the MSI during the first uninstallation, and then, during the second uninstallation (the version that shouldn't be there in the first place), I don't get any MSI log files -- all I get is the bootstrapper log file.
Can anyone shed light on this problem?
OK! I managed to recreate the problem in a toy program, so, hopefully, solving this problem should be much simpler!
Mr. Asmul, I appreciate your interest. However, I solved the problem. I made a very, very dumb mistake that I'm far too embarrassed to admit. Safe to say I've been chasing my own tail for two days and costing my employers money because... well, I was dropped on my head as a baby, and as a result I'm none too bright.
Your problem is indeed common, at least on the face of it, but I don't quite understand the whole problem scenario. When you have two versions of the same MSI in add/remove programs your major upgrade has failed. When you then uninstall one of the versions, you will get the log file entry you indicate:
Disallowing uninstallation of component: {GUID-HERE} since another client exists
Essentially each MSI component is installed twice with a ref-count of 2 because two versions of the same MSI is installed. Uninstalling both MSI setup versions should correctly remove the components in question (because then the ref-count goes down to 0 for the components).
"This MSI can only run during the initial install" - what does this mean exactly? I have read it again, and I am afraid things are just not clear to me.
These other MSI files, the suite - what are they, what do they install, do they install to the same or different locations? Why are they separate MSI files if they always install together?
Please prefer to update your question rather than adding too many comments.
While not strictly the same as the question, I'll add a variant of the same problem. I was using my own custom bootstrapper application (BA) and getting the same problem. This was because I hadn't added support to the BA to process command line args and run silently. Specifically the upgrade will run the old BA telling it via the command line to run silently and do an uninstall (which I wasn't handling).
As an aside if you are implementing your own BA, I highly suggest you download the WIX source code as it also implements a custom BA.
PS: This thread provides a range of options for getting upgrades working correctly. Note that some of the options like using the Upgrade/UpgradeVersion pre-date other options like the MajorUpgrade element.
How to implement WiX installer upgrade?
I've created a WiX Installer with Product Version as 1.0.0
<Product Id="*" Name="My Application" Language="1033" Version="1.0.0" Manufacturer="My Client" UpgradeCode="182bbc7d-8cc2-4014-9e1c-29312598bxc0">
I'm using MajorUpgrade Element for Upgrading Installer as follows:
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
Scenarios:
Scenario 1: Installing version 1.0.0 on already installed version 1.0.0
On installing the same version, the installer asks to either Repair or Remove, which is what I want and working fine.
Scenario 2: Installing version 1.0.0 on already installed version 1.0.1
On installing the older version, the installer throws error, A newer version of My Application is already installed and exits on clicking OK.
I want my Installer to display this error and continue installation by removing version 1.0.1 and installing 1.0.0
Scenario 3: Installing version 1.0.1on already installed version 1.0.0
On installing the higher version, the installer doesn't ask any thing and continues the installation by removing 1.0.0 and installing 1.0.1
I want my installer to ask for confirmation that whether to upgrade to higher version or to cancel the Installation
How can this be implemented?
To allow downgrades you need to set the property "AllowDowngrades" in the MajorUpgrade element. Go through all the attributes in the MajorUpgrade element from the below link.
WiX MajorUpgrade
The default behavior of upgrades is that they just happen. I think the assumption is that most people know what they are doing when they install an upgrade (or downgrade) and keeping intervention to a minimum is a good thing, and also in a silent upgrade install there is no way to ask for confirmation anyway - it just happens.
So in addition to allowing downgrades you'll need to add a confirmation dialog based on the property WIX_UPGRADE_DETECTED, maybe add an upgrade dialog that is shown conditioned on that property. That's a little awkward because all you know is the ProductCode of what you're upgrading (that's the value of WIX_UPGRADE_DETECTED) and no other information about the version that's already installed. So all you can say is that you are upgrading (or maybe even downgrading) the installed version. To get the information about the already installed product you'd need to query the system for the name and version of that ProductCode using something like the Win32 MsiGetProductInfo() API. That might require privilege (the UI sequence does not run elevated even if you are admin) so things get tricky pretty fast.
This is a fairly common question, so it's possible that someone has already done something, but a quick search didn't find anything.
I am a great fan of continuous integration, deployment and delivery. I believe that revision based upgrades is way to go here but it seems like using WIX based installers makes it really hard to support this feature. I am currently trying to change installer of our product so that it can be installed side-by-side (multi instance support) and allow revision based upgrades. In my case I want to allow installation of 1.0.0.0 and 1.0.0.1 version of product side by side and also support upgrade any of installation like just allowing upgrading from 1.0.0.1 to 1.0.0.2 without changing 1.0.0.0 version of product.
So in given scenario,
When installing 1.0.0.1 on top of 1.0.0.0, then 1.0.0.0 needs to be upgraded.
When installing 1.0.0.1 as new instances, then both 1.0.0.0 and 1.0.0.1 needs to be co-exist on same box (Installation will use different location). It should installed like a new one and display in Add/Remove program twice.
In future 1.0.0.2 should be able to upgrade any one existing instance (1.0.0.0 or 1.0.0.1) without changing other instances.
Installing 1.0.0.1 on 1.0.0.1 should perform usual repair.
Installer should prevent downgrade.
I tried Wix MajorUpgrade element but it didn't work the way i wanted. Here is complete result of my experiment.
1. Install 1.0.0.0 then upgrade to 1.0.0.1. It works well (as expected)
2. Install 1.0.0.1 as new instance then both 1.0.0.0 and 1.0.0.1 co-exist on same box (Works).
3. Install 1.0.0.2 as upgrade to 1.0.0.0 (not 1.0.0.1). Here is problem. It uninstalls everything (both 1.0.0.0 and 1.0.0.1) and didn't installed 1.0.0.2 properly.
Last result was really weird and i am not sure how to make that work where installation should upgraded target version only without uninstalling all instances ? Any help or guidance will be really appreciated.
<Product Id="*"
Name="$(var.ProductName)"
Language="1033"
Version="$(var.Version)"
Manufacturer="$(var.Manufacturer)"
UpgradeCode="MY-UPGRADE-CODE">
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
You'll need to stop using the MajorUpgrade element and build version specific upgrades. MajorUpgrade is basically a short and sweet way to get every prior version upgraded. Instead, you need to build specific WiX Upgrade elements that target the specific version range you want to upgrade. Your 1.0.0.2 would have an Upgrade element that targets only version 1.0.0.0 for the upgrade.
Can't say much about the failed upgrade without more detail as to what you mean about not installed properly. I note that you have your upgrade scheduled after InstallInitialize, and that means that you'll need to increment file versions to replace files and follow component rules if you're installing the same resources to the same locations. Maybe that's where the issue is.