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
Related
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/
I'm creating a Windows installer for my app using WIX, so, I start in the usual way:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="*" Name="Project X" Manufacturer="X LLC" Language="1033"
Version="1.0.0.1" UpgradeCode="PUT-GUID-HERE>
<Package InstallerVersion="301" Compressed="yes" InstallScope="perMachine"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed."/>
Because the Id is set to *, every time I build an MSI it has a different id, but the UpgradeCode remains the same. This successfully achieves replacing the old one with a new one when there's an upgrade in version (1.0.0.2 for example).
The MajorUpgrade entry prevents a lower version, such as 1.0.0.0, from being installed.
If I run exactly the the same MSI file, it shows me a dialog to repair, uninstall or change the installation parameters.
My problem is that if I re-build the MSI, and run the new one, it installs as if there's no other copy of Project X installed and the user ends up with two entries in the Windows Apps & Features.
Is there a way to prevent that? Is there a way to prevent it without having to modify (and commit) my .wxs file or another build file each time I build? I try to have my builds as automated as possible and having to open a file a change it each time would be really annoying.
Regarding passing the version number to candle.exe, it doesn't solve the problem. That would still require storing the version number in the repo, creating commits for each test of the installer. It's the same problem whether I have to write the number manually in the wxs file or I have to write the number manually in the pom.xml (that's the build tool's config) or whether it's generating during build and stored on a file that then I have to commit to the repo so that the number keeps monotonically increasing for myself and all developers involved.
In case this matters, I'm using Git as my source control system, and Maven as my building tool, calling heat.exe, candle.exe and light.exe. Specifically, I'm not using Visual Studio.
Regarding the similar question WIX. How to perform Major Upgrade with same version and different product code?, both the question and the answer assume it's ok to modify the .wxs file to increment the version number each time you build an installer to test. I don't think it's acceptable. I already knew this was possible because this is what MajorUpgrade does and I took note in this question.
I am in a hurry, I don't have time to read your question in the detail I would like to. However, skimming it I think I dealt with something similar a while back, and I decided to try the old-style major upgrade elements in WiX to get more control over how the Upgrade Table ends up being populated. The Major Upgrade is a convenience feature, using the old-style elements you get more fine grained control of the Upgrade Table.
I am not sure whether this is what you are after, but let me try to link to the answer I am referring to: Doing Major Upgrade in Wix creates 2 entries in Add/Remove Programs. As I recall it, I changed it so running a same-version MSI with different product codes triggers a "downgrade not allowed-message", and hence prevents a new version from installing on top of an existing version. You can then uninstall the old version from Add / Remove programs manually, or right click the old MSI and select Remove. Right clicking the new MSI and going Remove will not work - since this MSI has a new product code, and will not be able to uninstall the previous version this way.
This is because your ProductCode GUID is being randomly generated each build but your ProductVersion isn't being incremented. You need to follow the format 0-255,0-255,0-255 (fourth allowed by ignored per spec) and increment it each build. Then each MSI will perform a major upgrade resulting in one entry.
This machine is now in a bad state so cleaning it up could be fun. I'd uninstall all the legacy instances first then move forward.
Generate the version number in the build system and pass it to the candle.exe command line:
candle.exe -dProductVersion=<value>
Then refer to the preprocessor variable:
<Product Version="$(var.ProductVersion)" ...
Note that only the first fields in the product version are limited to 255. The third (and fourth, if you use it) can be up to 65535.
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?
When I try installing an upgrade built with WiX, I get the error "The specified account already exists" and yes, I have read Windows msi: error 1316: the specified account already exists
I'm confused about the role of the various GUIDs in the WiX project files.
Previously, I had released ver. 5.4.35 of my program; the Product.wxs file created an MSI and contained the following directives:
<Product Id="4DF780D3-60EC-43D3-A537-8484FE03B793"
Version="5.4.35"
UpgradeCode="A2F60910-A7FC-4B96-9375-EFBED25CC826">
The Burner created an EXE from the MSI with the following Bundle.wxs file:
<Bundle Version="5.4.35"
UpgradeCode="0694ce56-8095-450c-9859-881c0c9d56f7">
I published a new version 6.0.6, and changed nothing other than the version. The new Product.wxs is:
<Product Id="4DF780D3-60EC-43D3-A537-8484FE03B793" Same
Version="6.0.6"
UpgradeCode="A2F60910-A7FC-4B96-9375-EFBED25CC826"> Same
and the Bundle.wxs is:
<Bundle Version="6.0.6"
UpgradeCode="0694ce56-8095-450c-9859-881c0c9d56f7"> Same
Users are reporting that installing the new version on top of the old version fails, the "Repair" doesn't work. They have to completely uninstall the old version, and install the new one, which is inconvenient.
The installer does contain some custom actions. There are no component or other GUIDs.
My question: what should I change to insure that the upgrade works correctly and is error-free?
See if this helps:
The ProductCode is the guid that identifies that this product is installed on the system. You cannot install the same product twice (in the same context, strictly speaking, such as per machine). The product is already installed, by definition, so trying to reinstall it causes (usually) a maintenance mode repair action. Unless your custom actions have an appropriate condition they will run again - if there is a custom action that runs when its owning component is installed then it will run again when the component is reinstalled as part of a repair, so it will try to create the user again.
So a new ProductCode is required for a major upgrade because you now have a new complete install of the product that just happens to remove an older version of the product if there is one.
The UpgradeCode guid is a product line attribute. When you ship Product 2012, Product 2013, Product 2015 where each replaces the older one then they will use the same UpgradeCode precisely becaue this is used to search for those earlier products and upgrade them.
A major upgrade also requires the ProductVersion to be incremented in the first 3 digits, have a new PackageCode (usually automatic) and will upgrade only the same context (e.g. per machine will upgrade per machine but not per user install).
Also, the bundle codes are modeled on the MSI method but are not connected. The idea is that bundles have the same architecture - they need to detect current ones and upgrade older ones, so they use upgrade and product codes too,
In your case, you are trying to install the same ProductCode, which is not a good start to creating a major upgrade.
I think bundles produce verbose logs of the MSI activity, so they can be very helpful.
The Product.Id is the identifier between different versions. It works more or less like this:
The MSI engine searches the registry for the matching UpgradeCode.
If it encounters it, then MSI searches for the ProductCode (Id in WiX).
If it encounters it, then MSI stops the upgrade.
If not, then it searches for the version and compares if it is performing a downgrade or an upgrade.
The solution is to change the Product.Id for the new version. In my projects, I use Product Id="*", as in my case the version is updated every build.
I have my installer coded in WiX language. It supports major upgrade mechanism. A particular requirement is that the same MSI file will not be possible to install twice.
Now comes the tricky part: if user install and then try to install it again (UI mode) the installer enters in maintenance mode and everything works OK (Change/Repair will appear disabled.)
However when installing as our use case states in silent mode
msiexec.exe /i installer.msi /qn
The second install will proceed to install as normal (we don't want this!)
Some things to noticed about are:
In the log file of the second installation the sequence "FindRelatedProducts" will be skipped (as state in microsoft documentation http://msdn.microsoft.com/en-us/library/windows/desktop/aa368600(v=vs.85).aspx)
Also I research a bit an here http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/UpgradeVersion-is-not-detecting-the-same-version-preventing-downgrades-td5875840.html there is good information, claiming that for this scenarios we can used Installed property to detect if Product is already installed...
However, I get stuck here: because I have to avoid installing previous or same versions than current one and allowing upgrades greater, How could I achieve this in WiX?
Thanks for your help!
First all, you shall fix your upgrade code:
<?define ProductVersion = "0.0.2.3"?>
<?define UpgradeCode = "PUT-GUID-HERE"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Name="Asd" Language="1033" Version="$(var.ProductVersion)" Manufacturer="Me" Id="*" UpgradeCode="$(var.UpgradeCode)">
Note that the product code is recreated each time you build the installation (by not using the GUID but the asterisk).
The fundamental information is the product version and the upgrade code. The product code identify the specific deployed release, while the upgrade code identity the product releases "family". Softwares having the same upgrade code can be switched with each other. Softwares having the same product codes cannot be installed toghether.
Here is the trick to make upgrade you software:
<Upgrade Id="$(var.UpgradeCode)">
<!-- Detect older product versions -->
<UpgradeVersion OnlyDetect="no" IncludeMinimum="yes" IncludeMaximum="yes" Minimum="0.0.1" Maximum="$(var.ProductVersion)" Property="PREVIOUSVERSIONSINSTALLED"/>
<!-- Detect newer product versions -->
<UpgradeVersion OnlyDetect="yes" IncludeMinimum="no" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED"/>
</Upgrade>
<!-- Exits successfully in the case newer version are already installed -->
<CustomActionRef Id="WixExitEarlyWithSuccess"/>
By using the above markup, you say to Wix abort installation when he find a product having the same UpgradeCode but the installed one has a Version greater than the current one, but begin the installation (upgrading the current one) if he find a product having the same UpgradeCode and the installed one has a Version less than the current one.
The IncludeMinimum and IncludeMaximum shall do the trick, allowing the upgrade to skip the current version.
Wix doesn't install the same product: you shall be sure that the product code is the same for installed software and MSI-packaged software: if they are different, they are different deployed softwares. Beyond this, if the product has the same product code of the MSI, the installation offers the repair/change options: to disable them you have to play with the Property table of the Wix package, by introducing the ARP_ variables (you can disable repair, change and uninstall, but also setup manufacturer contacts and other properties).
Here is the ARP variable list. I don't know what is their behavior when installing in silent mode, but if you are invoking msiexec from command line, there is a specific repair option to issue repair (/f), so how can it automatically repair your product if you are not requesting?
This cannot be done.
When trying to install an already installed package, Windows Installer automatically performs a repair. There is no upgrade process.
Also, the maintenance process is triggered based on ProductCode. When launching your package the second time Windows Installer sees that its ProductCode is already installed and enters maintenance mode. It's not related in any way to upgrades.
Upgrades are used only when changing the ProductVersion and ProductCode.
Edit:
To prevent an automated repair in maintenance mode you can try this:
write a win32 DLL custom action which detects if the product is installed or not
if it is, this custom action should return 1602