How should I handle product upgrades in a WiX installer? - wix

I have a reasonably large WiX installer (250 Mb plus) and I am trying to come up with a suitable upgrade strategy.
Most of the files in the installer will not change and we would prefer not to have to distribute the whole package when only one or two files have changed.
I have looked into major and minor upgrades and my understanding is that a major upgrade will happen if the Product ID changes, so long as the Upgrade ID stays the same and minor upgrade patches can be used if both of these values stay the same.
My feeling is that a minor upgrade using a patch would be the best option to handle the cases where only a few files change and only to rebuild the whole installer when a substantial number of files change.
I have tested this using "torch" to produce a "wixmst" file based on the differences between two "wixpdb" files, then building a patch from that. However, I found that I can only patch from one version to another (e.g. 1.0.0 to 1.0.1, then 1.0.1 to 1.0.2 but not 1.0.0 to 1.0.2). Is it possible to target a minimum version for a patch and support any version above it?

Patching is a pain so get ready for a lot of it as you learn to master it. Here's another strategy that might work for you. Split your MSI out into 2 MSI ( Microsoft calls this Micropackages ). Have a Base MSI that contains the bulk of your content that is expected to not change and a Second MSI that is much smaller that contains your files you expect to be high churn.
Then use Burn is a bootstrapper to handle chaining these together and uninstalling them together. This is similar to what Visual Studio does.
Now you can just ship major upgrades of your second MSI.

I believe that it is possible to patch in the scenario you described above, as long as the patches are uninstallable. An example scenario would be:
Install msi (v1.0)
Install msp (v1.0 - v1.1)
Uninstall msp (back to v1.0) then install msp (v1.0 - v1.2)
For more information on uninstallable patches, see the wix documentation: http://wix.sourceforge.net/manual-wix3/patch_restrictions.htm
and the Windows documentation: http://msdn.microsoft.com/en-us/library/aa372102.aspx.
Note that to create uninstallable patches there are certain restrictions and you must be at WiX 3.0 or greater.
Like Christopher mentioned, patching can be a pain. I have found that in many cases, my managers may ask for the ability to do patch upgrades when all they really mean is for the user to be able to upgrade without manually installing first, which can be accomplished by a major upgrade just fine.
That said, if you have customers that require many small updates that get downloaded frequently, then patching may be worth the extra effort.

While Christophers answer is awesome in that he suggests the wix bootstrapper, I would discourage the route of doing major updates for the "high-churn" package. The problem is that after you have done your bootstrapping patch which internally does a major upgrade of your volatile libs in the HighChurn.msi from version v1.0 to v1.1, the bootstrapper will not, to my knowledge, re-install the previous package of HighChurn.msi in v1.0.
There's another path: you can certainly author patches which target the release of your main package. Given what you wrote I'm not entirely sure, but if your 1.2 patch can only be applied to 1.1, then you probably diffed your 1.2 only against 1.1, and not against 1.0.
Here's a neat guide how to create patches: https://www.firegiant.com/wix/tutorial/upgrades-and-modularization/patchwork/
Follow that guide, do superseding patches ([PatchFamily/#Supersede], it'll make v1.2 invalidate everything which v1.1 shipped, so you are basically forced to make v1.2 patch v1.0 and not v1.1), and add this flag to the patch element to target the major release, even though higher versions are present: Patch/#MinorUpdateTargetRTM="yes". Always diff your patches against the release installer (HighChurn.msi v1.0), never against the installer you used for a patch (HighChurn.msi v1.1).
There are of course situations where you might want to require a certain upgrade installed for patches: A well planned fixpack/servicepack scheme, for example, where patch 1.1.1 requires service pack 1.1 installed on top of the release 1.0.
A final word on patching your volatile data (I'm presuming versioned libraries here): You might want to have an eye on which libs you could basically replace in the patch. Then you can create patches with very few data, by only giving the changed libraries a higher version. If you increase the version on all of your libraries, all libraries are going to be patched, resulting in larger patches. This might require a slightly more complicated build workflow (God knows it did for us).

Related

Is there any possible way to perform upgrade when Product codes for old and new versions are same?

We have two installers build in WIX with the constraint that Product code has to remain same. On doing an upgarde from old to new, I get an error, "The specifile account already exists."
Does WIX allow any workaround for me to achieve an upgrade while keeping my product code unchanged.
It depends what you mean by "upgrade" but there is no such thing as a major upgrade where the ProductCode stays the same. Keeping it the same is not a constraint, it's against what a major upgrade does. You should say why you believe it's a constraint to keep it the same, and if you decided it's a solution to a problem you haven't told us about.
The error message is from a WiX util CreateUser custom action of some kind. You haven't specified what you have changed in your MSI file, but if you are just running your new MSI and it's got the same ProductCode then you are probably doing a repair, and that repair is running the CreateUser again and telling you it already exists. You should supply more info about your CreateUser.
You'll also need to say what kind of upgrade you are doing (major, minor?) and if it's minor then what is your command line?
Minor Upgrade: That is just a minor upgrade - a different form of MSI update from the more commonly used major upgrade. Info about Patching & Upgrades (in general).
Complex & Limited: There are a number of restrictions for minor upgrades that make most people end up using major upgrades. Essentially a minor upgrade can add new features and components, but cannot reorganize the feature-component tree. But wait, there are many more restrictions:
Minor upgrades can not change the MSI file name, it must match the previously installed version. I always end up banging my head against this one having forgotten the restriction, hence this specific mention.
Some further limitations as capably explained by Flexera's help file: Major Upgrade vs. Minor Upgrade vs. Small Update (third column).
Aging, but good content from installsite.org on the same topic: Windows Installer Updates and Patches.
MSDN description of limitations: Changing the Product Code
Advanced Installer's Creating Patches list of limitations and restrictions (applies to minor upgrades in general as well as minor upgrades delivered as patches).
Installing Minor Upgrades: A minor upgrade can be delivered as a regular MSI or as a patch file. The standard command line used to install a regular MSI file:
msiexec.exe /i MySetup.msi REINSTALLMODE=vomus REINSTALL=ALL
Maybe see this Flexera help file page for some more details on installing minor upgrades (some Flexera-specific stuff, but mostly generic). That is where the above command line is from.
Personal Opinion: Let me end with a subjective observation. I find minor upgrades excruciating for real-world use, and I have only successfully used them for "hotfixing" (just update a couple of files with no other changes), and to fix errors in installed product's uninstall sequences which prevented them from successfully uninstalling. In these cases the minor upgrades became so simple that they worked reliably. In order to deliver a real-world product with only minor upgrades, a lot of care, foresight and discipline is needed (not to mention a patient and insightful product manager who will understand these technology limitations and what they mean for real product deployment).
With all that said, let us not underestimate the huge, corporate benefits of MSI (beyond mere upgrading issues and related details):
The Major Benefits of MSI (compressed - "executive summary")
The Corporate Benefits of Using MSI Files (elaborate and verbose)

MSI uninstallation sequence after an MSP was installed

I had an MSI with a CA type 1. Later on, I realized that CA had to be changed so I updated it and created an MSP.
Q1: If I install the MSI and then apply the MSP, I don't think the cached MSI (one in Windows\Install directory) contain the updated CA, right?
Q2: If I uninstall this MSI, does the installer uninstall the MSP first and then the MSI?
Q3: Which CA would be performed during uninstallation? An updated CA or the original CA? Or an updated CA first and then the original CA?
Thanks in advance.
In (typically) the \windows\installer directory there is the cached MSI and any patches that have been installed for that product. When some installation action is performed the cached MSI and all its related patches are "merged" to create the view of the actual currently installed patched product, so:
So Q1 doesn't really apply because nothing is done with the cached MSI on its own. If you look at it with Orca it won't reflect the patch, because that's in a separate MSP file.
Q2: There is no first and last because the (MSI+Patches) is what is uninstalled, followed by clean up removing the files that are no longer needed.
Q3: There is only one CA in (MSI+Patches) and that's what is called.
PhilDW has attended to your specific questions, maybe I can make a few guesses as to what the underlying problem really is.
Is this a minor or major upgrade MSP? A minor upgrade patch can be used to "hotfix" errors in the installed MSI's uninstall sequence - if that is what you are really asking. I have done so many times, and when you install the patch first and then uninstall, what is running on uninstall is what you included in your MSP - the new CA - provided you installed everything correctly (command line, etc...). The MSP is merged to the cached MSI - as Phil states - at runtime. What I am a little fuzzy on, is how any applied transforms are handled - this is something I have never had the time to test. Are you using transforms?
This approach is frequently used when you discover an error in the installed setup's uninstall sequence which prevents a major upgrade from running correctly. In a regular major upgrade the old custom action may or may not run from the old setup depending on how it is conditioned (see link for some conditioning cheat sheets), but typically it either runs undesirably, returns an unexpected error that triggers an undesirable rollback or the whole custom action crashes, causing a failed major upgrade (or failed uninstall).
The above yields a catch 22 situation where your existing install appears un-uninstallable and un-upgradeable - but a minor upgrade can come to the rescue (a regular MSI installed as a minor upgrade should also work - it shouldn't need to be delivered as a patch, provided that you properly re-cache the new MSI from the command line - a patch is merely a distribution mechanism for an upgrade that is already working).
A major upgrade patch (MSP), on the other hand, will not allow you to fix errors in the uninstall sequence of the existing installation since it triggers the uninstall sequence of the pre-existing install and just tells it: "uninstall yourself" - as part of the major upgrade operation. When this happens, then the old CA is used - which is embedded in the cached MSI for the old setup. It is the old setup running - unchanged.
It has been over a decade since I made a major upgrade patch - I find them pretty bad and I avoid them if possible. There are too many problems - and honestly: a few serious logical flaws (for example the fact that the product you are trying to patch may already have been uninstalled - if you schedule RemoveExistingProducts early - see below - a rather ridiculous error, one would have to say). I have never made a major upgrade patch using WiX, but I tried with Installshield and briefly with Wise. In order for them to run at all, you have to set the uninstall of the old version to happen after the install of the new version (so the old version isn't already gone by the time you try to patch). This means RemoveExistingProducts must be late in the InstallExecuteSequence - which makes the setups vulnerable to component referencing errors (another common problem).
UPDATE: I should also add that my major upgrade test - done many, many years ago - also had problems with feature state migration (MigrateFeatureStates) - the patch caused all features to show up in an unknown state. To this date I have never had the time to figure out exactly what happened, but I think it may have been my own doing. I did something funky with the Preselected property (I think it may have been related to a merge module doing something stupid - and I tried to "fix" it - with another fix that didn't fix anything, but caused new problems - and such forth and whatnot :-) - deployment is fun). Just reporting the failure, and whatever intel I have - not claiming to have any solutions. There were also other problems - but most of them were Installshield specific I think. WiX might do a lot better. Wise was sensationally good for minor upgrades (they really did work), but I never used Wise for a real major upgrade.
A typical major upgrade custom action problem is that the custom action is erroneously conditioned and will run in both the old version's uninstall, and the new version's install. There are many modes to test your conditions in, and you will be surprised if you take the time to do so: install, repair, modify, uninstall, patch, etc... And you will often find that the custom action runs unexpectedly on modify or repair operations or similar. I linked to a couple of cheat sheets for conditions above, here it is again: Is it possible to run a custom action only in repair mode.
UPDATE: And a common patch problem is that custom actions may run unexpectedly because they are not conditioned with NOT PATCH. Rant: I wish patching would be its own thing in MSI and not just a delivery mechanism for a regular update, and that it would target files only and have its own installation sequence (like admin install has). This would allow "targeted patching" and small hotfixes for huge products - which really need some working, down-to-earth patching that is not overambitious and over-complicated (which is what patching in MSI currently is - in all honesty).
Advice? Use a minor upgrade patch or a regular minor upgrade (not delivered as a patch) to fix the uninstall problem, and then proceed to use your normal upgrade approach. It should be possible to deliver all this in a WiX Burn bundle - but I have never had time to test it.
My 2 cents? Forget patching if your product is small, and just use a regular minor upgrade MSI. If your product is huge, then use a patch package (or your download bundle will be a lot larger than necessary). Be aware that your future setup bundles should also contain the "hotfix" patch / MSI to allow users with older installations to fix the uninstall error before installing the latest version. A little clunky, but it should be manageable. If your old setup has a working uninstall, but fails as a major upgrade (because of an insignificant error in the uninstall sequence making the whole process fall over), you can uninstall the old setup with a regular uninstall command passed to msiexec.exe and then install the new version afterwards (avoiding the major upgrade scenario by performing a manual uninstall first). I haven't tested this with Burn yet.

Minor upgrade with Wix Patching

I have an installer for Wix which installs the program to be version I have successfully made patches to achieve the following upgrading:
1.0.0 -> 1.0.1
1.0.0 -> 1.0.2
1.0.1 -> 1.0.2
This works I've had to make new .msp files from 1.0.0 to the target build number each time. So from my understanding how the patching works behind the scenes, is that if I had initially a patch from 1.0.0 to 1.0.1 then I created a new on to go from 1.0.0 to 1.0.2, if I were to run the new patch, the old patch would be uninstalled and the new one would replace it.
If my understanding is correct then this means that patch files would continue to increase in size the more you change code, so I would like a solution to counter this, where at some point I would increment the minor version, and start the patching process over.
For example I would like to do this:
1.0.0 -> 1.0.12 could be handle with patch1.msp. Then I create a patch2.msp which would start creating patches based off of version 1.0.12. An example upgrade path might then look like:
1.0.0 -> patch1.msp -> 1.0.12 -> patch2.msp -> 1.1.0 -> patch3.msp 1.1.0 -> 1.1.x
Is there any way to accomplish this? Or would I need to reinstall with a .msi file and continue to patch from there?
First, installing a superseding MSP does not remove superseded MSPs. The superseded MSP is simply marked as superseded (inactive). Should you later remove the superseding MSP, the previously superseded MSP is reactivated.
In order to remove MSPs, you need to use the older obsolescence method, but I really don't recommend that. Not only is it difficult to manage, it also means that, for example, if you fixed a security bug in a previous patch that was removed, when the newer obsolescing patch is removed the security hole is unpatched. That's the beautify of supersedence, which has been around since MSI 3.0.
To your question, though, I don't recommend it. It's best that MSPs target the baseline. Yes, they could potentially get a little bigger, but only if you're adding content. If newer versions are just updating sets of files or other resources, an MSP targeting a single MSI should never grow larger than the base MSI (well, MSI + external CABs, since CABs are embedded in the MSPs and always should be). See https://blogs.msdn.microsoft.com/heaths/2007/03/30/small-updates-should-usually-target-a-single-baseline/ for more about small update MSPs, and https://blogs.msdn.microsoft.com/heaths/2006/06/14/cumulative-service-packs-with-minorupdatetargetrtm/ for how to support targeting a single baseline with minor update MSPs.
It is possible, though. You need to save the upgrade MSIs when building each patch, so when you create your 1.0.1 MSI to effectively diff against 1.0.0 to build your MSP, then when you build your next MSP you need to diff 1.0.1 against 1.0.2. These MSPs must be minor update MSPs, though. That means that the ProductVersion property is included in the patch authoring transform; otherwise, the MSI 1.0.0 + MSP 1.0.1 view won't change the ProductVersion, so MSP 1.0.2 would never be applicable. You should start to see where this gets difficult to maintain for you (not to mention forces the customer to have to install every previous version MSP, which is not a great experience for them either if they are just starting out from your RTM).
In summation, keep it easy for your customers. Just target the same baseline using the MinorUpdateTargetRTM property in the MsiPatchMetadata table of the MSP itself.
In my experience the usual path is that at some time you create a major upgrade MSI (see WiX majorupgrade element). This MSI with new ProductCode and version greater than the last patch version (e.g. 2.0.0) will upgrade all versions betweeen 1.0.0 and 1.0.12. Then you start patching based on the 2.0.0 product.
There are options in patches to patch by replacing each entire file or by binary patching of each file - I'm not sure which you are using, but obviously if you make a small patch to a huge file the patch will be larger than if the patch is a binary update to that file.

How can a wix installer downgrade merge-module files during a major version upgrade?

We have an installer that consumes a merge module. The newest version of the merge module includes downgrades to some files. When using the installer to upgrade from an earlier version we are having problems downgrading these files.
Initially the files from the merge module were being removed and not re-installed, but after reading wix major upgrade not installing all files I set Schedule='afterInstallFinalize' on the MajorUpgrade element. This resulted in the files with the newer versions being retained.
How can we change either our installer or the merge module so that these files are downgraded during an upgrade?
Well, in my opinion, the best way to approach this issue is to sequence the standard action "RemoveExistingProducts" to before CostInitialize standard action.
Be aware that this scheduling is not in accordance with the Microsoft recommendation at :
https://msdn.microsoft.com/en-us/library/windows/desktop/aa371197(v=vs.85).aspx
So, when you try to build your msi package, you might have to end up suppressing ICE error messages ,which if not suppressed, might prevent you from building.
There is an easy way to suppress ICE error messages in Wix . You can do that in the Visual studio IDE as well as when using the candle.exe to compile your .wxs project. The Wix documentation will give you enough details about this.
If you are wondering if its ok to go against the Microsoft recommended placement for RemoveExistingProducts, take a look at :
Downgrade File in MajorUpgrade
FWIW, I've talked to MS support in the past about having REP before costing to make upgrades work successfully, and at that time they said it was ok, while pointing out that it's also before MigrateExistingFeatures so if you migrate features during upgrades there'll be an issue.
What this means is that , if you have multiple features in your msi package and you want the exact same set of features to be upgraded by your upgrade package, then this approach might not work.
However, if you just have a single feature in your msi package, then this approach will work.
Also, be aware that placing RemoveExistingProducts outside of InstallInitialize and InstallFinalize has other consequences, in case there is an error during your upgrade, as RemoveExistingProducts is not transacted.
What might happen is that , RemoveExistingProducts will uninstall your old application and then the upgrade process starts the installation of your newer version of your product. However, at this point of time, if there happens to be an error installing your newer version of your product, then the upgrade rolls back and then you will be left with no version of the product on your system.
http://blogs.msdn.com/b/heaths/archive/2010/04/09/major-upgrades-with-shared-components.aspx
-The other option is to make use of REINSTALLMODE property.
You will author this property in your property table with a value of emus
REINSTALLMODE = emus.
If emus doesnt work, try with amus.
using amus is fraught with risks and should be avoided for the most part, except in exceptional circumstances.
https://msdn.microsoft.com/en-us/library/aa371182(v=vs.85).aspx
However, exercise caution here again.
REINSTALLMODE are caller properties and are usually set by the person performing the installation and hence its not a good practice to author this in the Property table.
However, there might be exceptional situations such as yours which might require you to take this approach.
-The other option i was thinking was to change the component GUIDs of the components in your Merge module.
However doing so would only work if the following condition is met:
-All the consumers of your merge module have RemoveExistingProducts sequenced very early in the upgrade cycle i.e they follow a method of ugprade where the older product is uninstalled and a newer product is installed.
So this might lead to re-sequencing of RemoveExistingProducts in all of your consumers.
Reason being, assume for a moment that you change the component GUID in the present version of the merge module and then you rebuild the latest version of the installer using this merge module. If RemoveExistingProducts is sequenced later in the upgrade cycle i.e after InstallFinalize, then it's a violation of windows installer component rules. You have two products installing the same file to the same location but with different component GUId's. Hence, its absolutely critical that if this approach is followed, RemoveExistingProducts is sequenced very early in the upgrade cycle.
Hope this helps.

Major vs. Minor upgrade in windows installer

Is there any reason not to set up the install so that major upgrade is always done and productcode changed?
I find that supporting different kinds of installs needs more code, and "repair" install seems to work easier with major upgrade. Also the application that needs to be installed is not very big, thus there is no need for "service packs" or patch installers.
No. If you application is small and you don't feel the pain of uninstall and install then Major Upgrades are the easiest thing to do.
I'd only move to the more advanced update mechanisms if the Major Upgrade user experience was unacceptable.
I generally find that minor upgrades are only useful in a few cases:
1: Uninstall Bug: There is a bug in the uninstall sequence of the installed MSI. Since a minor upgrade does not uninstall the product, but merely reinstalls it. This allows you to fix whatever was wrong in the uninstall sequence before it is called.
2: Hotfix: There is a very small tweak required for a very large product. Say a bug fix for a single file or a few files. There will generally be a small bug requirement after a couple of weeks for all large products where you need to replace just a few files. Major upgrades can be terrible for this - uninstall and reinstall for just 4 out of 10000 files?
3: Patching: You want to deploy a patch for your product. MSI does allow major upgrade patches, but these are even more complex to get working than minor upgrade patches (which are also difficult).
The "Small Update" feature should never be used for any purpose in my opinion. Major or Minor upgrades only.
Update type Change product version? Change product ID?
Major upgrade Yes Yes
Minor upgrade Yes No
Small update No No