Uninstall different product at install and major upgrade - wix

Two different products have different UpgradeCodes and exist in two different setups (ProductA.msi and ProductB.msi). Both have version N.
Now ProductB is merged into ProductA version N+1. That is, ProductB's files will be provided by the installer of ProductA, and to the install location of ProductA.
A user that installs ProductA version N+1 would not like ProductB to be installed any more (it could even cause problems). So when ProductA is installed/upgraded to version N+1, ProductB (any version) should be removed. How can I accomplish this in the setup of ProductA?
It's similar to this question, but that is for removing a different product at uninstall rather than at install/upgrade. Wix - uninstall different product

WiX Sample: Here is a technical sample of doing as Bob Arnson describes: Adding entries to MSI UpgradeTable to remove related products. Make sure you leave this entry in your setup for future releases. It needs to persist there as people can skip a few version when upgrading?
Inline Sample: Please see link above for full sample.
<!-- Older Product Line 1: Upgrade Code -->
<Upgrade Id="{11111111-1111-1111-1111-000000000000}">
<UpgradeVersion Property="PRODUCTLINE1" IncludeMinimum="yes" Minimum="0.0.0" />
</Upgrade>
Debugging Major Upgrades: WIX does not uninstall older version - an ad-hoc list of causes for major upgrade failure.
Component Referencing: Merging setups can cause some component reference errors. I assume you are aware. This could manifest as missing files after installation or "some malfunction" during upgrade scenarios. Faulty registration, stranded files, you name it - just mentioning.
Component GUIDs: Here is some background information on component referencing and component GUIDs: Change my component GUID in wix?
As a rule of thumb: If you install the old files to a new location with new component GUIDs you should be fine. Things to check: shared files, COM servers, anything unsual in terms of machine-scope registration, services, COM Interop, COM+, etc... Many setups are simple, others are not.
Custom Actions: Migrating any custom actions can cause serious problems - especially during upgrade scenarios with complex sequencing and conditioning for when the actions actually run and not.

Add ProductB's upgrade code to a new Upgrade element in ProductA. Then when installing ProductA N+1, the upgrade will remove both ProductA N and ProductB.

Related

Adding entries to MSI UpgradeTable to remove related products

A WiX installer product node has an attribute UpgradeCode. It is used to refer to previous versions of the same product. The value is stored in the UpgradeTable. The UpgradeTable is parsed by the FindRelatedProducts action.
The UpgradeCode allows to remove previous products with the same UpgradeCode. But the plan is to integrate several outdated legacy products to a combined single product. The UpgradeCode of this legacy product is known. I hope adding this code to the UpgardeTable will remove this legacy product too. This can be done by filling the UpgradeTable.
How can I add more entries in the UpgradeTable in a WiX setup?
Edit: What Syntax is required?
Is there a better way to remove products that are absolete after an upgrade?
Short Answer: You add several Upgrade Element entries in your WiX
source which will create several rows in the compiled MSI's Upgrade Table which then list products that are to be uninstalled during
installation (or that can abort your installation). You must be very careful about the options you specify for each product family to uninstall.
Major Upgrade Failure: Here is a list to help debug failing major upgrades by identifying the most common problems: Common causes of failed major upgrades.
Side-By-Side Installations: Be aware that an alternative to uninstalling older versions during a major upgrade, is to make your new version isolated enough to be able to co-exist with existing installations. Such isolation can be challenging, and is a whole other ballgame (prevent: fighting over file associations, incompatible COM server installations, incompatible runtimes, conflicting services, unexpected locks of configuration files and registry keys, etc...).
MajorUpgrade Element: Newer versions of WiX feature a "convenience feature" for major upgrade implementation in the form of the MajorUpgrade element. This elements simplifies the implementation of normal major upgrades.
Upgrade Element: In earlier versions of WiX more basic elements had to be used to implement major upgrades. This element is still available, and it is what you need to do more elaborate and fine-grained UpgradeTable configuration.
The differences between using these methods are very nicely illustrated by Wim Coenen here: Majorupgrade or Upgrade ID which is preferred for Major upgrade? I think that explanation is so good that I refuse to repeat it too much here :-). Give it a quick read please.
Major Upgrade Configuration Choices: The below is just a sample. The actual configuration of a major upgrade has to be carefully reasoned in each case:
Do you want to abort if higher versions are found?
From what product line?
What will the error message be?
Do you want to continue if an uninstall of an older version fails?
Do you want to allow lower versions to uninstall higher version? (please don't).
Do you want to allow the same version to uninstall itself and re-install?
You obviously have to plan for this and test in detail. Below is a mock-up. This combines the use of the MajorUpgrade Element and Upgrade elements. You can also rely solely on Upgrade elements to do things "manually" with more fine grained control:
<!-- Major upgrade - Your New Product Line, using the MajorUpgrade convenience element -->
<MajorUpgrade DowngradeErrorMessage="A later version of [ProductName] is already installed" />
<!-- Older Product Line 1: Upgrade Code -->
<Upgrade Id="{11111111-1111-1111-1111-000000000000}">
<UpgradeVersion Property="PRODUCTLINE1" IncludeMinimum="yes" Minimum="0.0.0" />
</Upgrade>
<!-- Older Product Line 2: Upgrade Code -->
<Upgrade Id="{22222222-2222-2222-2222-000000000000}">
<UpgradeVersion Property="PRODUCTLINE2" IncludeMinimum="yes" Minimum="0.0.0" />
</Upgrade>
<!-- Older Product Line 3: Upgrade Code -->
<Upgrade Id="{33333333-3333-3333-3333-000000000000}">
<UpgradeVersion Property="PRODUCTLINE3" IncludeMinimum="yes" Minimum="0.0.0" />
</Upgrade>
I would suggest you change the name of these PRODUCTLINE properties that is inherently understandable as a specific product line. In other words if you uninstall WiX3 you call it WIX3PRODUCTLINE etc... This is so the resulting log file is easier to comprehend.
Sample Upgrade Table:
The Attributes column of the Upgrade Table is important to control the behavior of the major upgrade. Continue on uninstall failure, etc...
And a list of free tools you can use to view a compiled MSI files (for whoever might find this answer): How can I compare the content of two (or more) MSI files?
UPDATE:
Unable to remove previous versions of MSI. Multiple entry's show up in control panel
WIX does not uninstall older version (potential causes of failed major upgrade)
Older Entries:
How can I find the Upgrade Code for an installed MSI file?
How can I find the product GUID of an installed MSI setup?
How To: Implement a Major Upgrade In Your Installer
Majorupgrade or Upgrade ID which is preferred for Major upgrade?
Major upgrades now easier than ever
Also want to send you to WiX expert Neil Sleightholm's site for some dated, but still good real-world samples:
WiX Script for Major Upgrades
LaunchConditions, FindRelatedProducts and Downgrades
Just add Upgrade and UpgradeVersion elements as required. That all just works. You might be using the MajorUpgrade element, and perhaps you're unaware of those other elements.

How to prevent Wix from installing an older version?

I have an application that we are switching over to a WiX installer. So far almost everything seems to be going well. The one problem I'm having is that if an older version is downloaded and attempted to install, it does so.
And that's a bit of a problem. If there is a newer version installed I don't want it to install the older version. I thought the problem was with the "Upgrade" component but I must admit I've hit a wall. How can I change it so that the older versions see there is a newer version already installed and not install it?
My test product is now in version 2.4 (the newest version we're trying to push out). It upgrades correctly to 2.4.1 or 2.5 or 3.0. But if I make a 3.0 version, and then run the msi for 2.4 it still adds it.
My upgrade component:
<Upgrade Id="PUT-GUID-HERE">
<UpgradeVersion Maximum="2.4" Property="PREVIOUSVERSIONSINSTALLED" />
<UpgradeVersion Minimum="1.0" Property="NEWERPRODUCTFOUND" OnlyDetect="yes" IncludeMinimum="no" />
</Upgrade>
Follow Up:
After following Steins suggestion I got an error like this
"Duplicate symbol 'WixAction:InstallExecuteSequence/RemoveExistingProducts' found"
After looking around in the Product.wxs file under the <InstallExecuteSequence>I had to delete <RemoveExistingProducts Sequence="6550" /> because that was the duplicate it was referring to. After doing that the installer worked and old versions can no longer be installed on top of new versions.
Packages of Futures Past: You can not change older versions of your package to detect newer ones. You need to build protection into your packages from the start. Packages need to be pre-cognitive. It's an industry problem.
Modern Times: The WiX elements you show above are "old-style". There is a new "convenience feature" described here: How do you detect installed product versions at each startup? It involves the "new" MajorUpgrade element. This new MajorUpgrade element features some auto-magic and I believe it adds the protection you describe by default (downgrade protection). Hence you can switch to using it. I would try that first. Let me inline the basic markup:
<MajorUpgrade Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."
AllowDowngrades="no" AllowSameVersionUpgrades="no" />
In addition to removing the old-style upgrade elements, please also remember to delete any hard coded scheduling of the RemoveExistingProducts standard action. For example, remove this line (sequence number will likely be different, but same name):
<RemoveExistingProducts Sequence="6550" />
Decoupling: If you find that there is a high risk that people will run the older versions and mess with your newest application, you could set a new installation location and a new upgrade code for your latest version and install side-by-side to decouple your old and new products.
Side-By-Side: For this to work your product(s) must be capable of co-existing peacefully and not fight over file associations, per-machine registered COM servers, or other globally shared data that make the products interfere with each other. Whether this is possible or not depends on your application. A globally shared COM server can not be registered from two different locations - if you use normal registry registration (you can use manifest based reg-free COM though - though this is involved at times). There can be many challenges to overcome before your application supports side-by-side installation, or it could be rather trivial if your package is simple with no registry involvement.
Component GUIDs: You need to set new component GUIDs as well - for all components - in addition to the mentioned change of upgrade code in order to really shield the products from each other. If you use WiX auto-GUIDs this will happen auto-magically. The reason you need new component GUIDs is attempted explained here: Change my component GUID in wix? Essentially a GUID reference counts an absolute installation location, not a file per-se. You install to a new location, you need a new component GUID.

Run Wix Custom action only during uninstall and not during Major upgrade

I am trying to delete a file using a custom action scheduled between InstallInitialise and InstallFinalize standard action.
MajorUpgrade element is used to design upgrades.
However, I want the custom action to run only during uninstall and not during the Major upgrade(this includes uninstall and install).
I have used the following conditions to execute the CUstom action:
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
REMOVE AND NOT WIX_UPGRADE_DETECTED
Is there a way to uniquely detect the Major Upgrade using properties in Wix?
Phil has already answered. I'll just post what I wrote a few hours ago
before heading out. The conditions you specify look pretty good to me.
Maybe I'll do a quick review of things that are likely to cause
confusion - such as what custom actions run when?
Major Upgrades: A major upgrade is really an install of a new application version combined with the uninstall of the old version - with different uninstall scheduling possible (uninstall old and install new, or install new and uninstall old). Hence, during a major upgrade operation, 1) the uninstall sequence runs only for the old setup, and 2) the new setup runs only its install sequence. This is of crucial importance to understand what custom actions runs when and why.
Custom Actions and Major Upgrades: To put it in other words: this sequencing can cause quite a bit of confusion for custom action sequencing, since it could appear that an action runs from the new setup, when it in fact runs in the old setup's uninstall sequence. If you are sloppy with sequencing, the typical error is seeing the same action run many times during the upgrade process - potentially twice from each setup (four times in total - or perhaps even more - I haven't tested that in detail) - if you run the custom action in immediate mode.
No Retrofitting for Major Upgrades: As Phil explains, you can not add a custom action that will run during the old setup's uninstall sequence inside the new setup. That custom action would have had to be part of the original setup, or added via a minor upgrade (which upgrades the existing installation in-place, rather than uninstall and reinstall it).
Important:
UPGRADINGPRODUCTCODE is set only in a setup that is being uninstalled as part of a major upgrade. It is not set in the new
version being installed.
The condition UPGRADINGPRODUCTCODE is hence not true in the installing setup, only in the uninstalling setup.
WIX_UPGRADE_DETECTED is set only in setups that are using WiX's MajorUpgrade element that have detected that another version is
being uninstalled as part of its install.
The condition WIX_UPGRADE_DETECTED is hence true in the installing setup, but not in the uninstalling setup.
WIX_UPGRADE_DETECTED: To go into even more detail, WIX_UPGRADE_DETECTED is strictly speaking not a custom WiX feature - it is a WiX standard or convention for setting the built-in MSI property ActionProperty for the upgrade process. All MSI files supporting major upgrades have such a property, WiX just names it in a standard way. The property is set in a column in the Upgrade table, and it is a property that is set when a setup finds related products - that are lower versions (and hence to be uninstalled) - on the same box during installation.
WIX_DOWNGRADE_DETECTED: Note that in a standard WiX-compiled MSI using the MajorUpgrade element there is also WIX_DOWNGRADE_DETECTED - the property used to list products found that are of higher version than the running setup. These would block the setup in question from installing - in most cases (unless the settings are customized by the setup designer).
The action property specified in the upgrade table can be "anything", but the MajorUpgrade Element "convenience feature" does this for you in an "auto-magical" way that makes sense for most purposes - using the mentioned property names WIX_UPGRADE_DETECTED and WIX_DOWNGRADE_DETECTED. Check the Upgrade Table of your compiled MSI to see how this works in detail. Here is a screen shot:
I wrote this other answer showing how to use another property name (YOURUPGRADEPROPERTY) as "ActionProperty": wix installer update process and confirmation dialog (the linked answer is not a recommendation, demonstration only). Just a link, probably not very useful for you now that I think about it.
Some Links:
http://forum.installsite.net/index.php?showtopic=13809
NOT UPGRADINGPRODUCTCODE evaluates to true on a major upgrade for custom action
It's not obvious whether you want to do this in the older installed product (which is presumably already shipped and therefore can't be changed without an update such as a patch) or in the newer upgrade install.
I'll also assume you've looked at the RemoveFile element and it doesn't meet your requirements.
The UPGRADINGPRODUCTCODE property applies to the older product being upgraded and uninstalled. If the file belongs to that installed product and you want to remove it only at uninstall with a custom action in that older install the condition on the custom action would be:
REMOVE="ALL" and not UPGRADINGPRODUCTCODE
but as I said, that custom action would need to be already in the older installed product and there's nothing you can do in your upgrade MSI to fix that.
If you are removing the file from the upgrade then the condition during an upgrade is only:
WIX_UPGRADE_DETECTED
It might also help to say where your major upgrade is sequenced. If it's early (such as around InstallInitialize) then the upgrade is basically an uninstall of the older product followed by an install of the newer product, and that might be related to the removal of the file, if that's what you're seeing.

How to prevent database drop during Wix Major upgrade

I am building an installer with Wix 3.10 that will install files, create a service as well as create and populate a database.
I am using the Wix sql:SqlDatabase element to create the database and run some sql scripts to populate it during installation (based heavily on WIX database deployment, installation)
As recommended in the Wix documentation, I am testing a mock upgrade before releasing the initial installer. From what I can tell sticking to major upgrades is strongly recommended and so I am using the MajorUpgrade element as per the examples.
Unfortunately however during the major upgrade I can't seem to prevent Wix from uninstalling the database, nor can I find any guidance on how to handle this. I understand that a major upgrade is effectively an uninstall of the current version followed by a fresh install of the new version, but surely there is a way of retaining parts of the original?
I have a similar problem with the service that I install too, but based on this SO question Wix Major Upgrade: how do I prevent Windows service reinstallation? the solution appears to be to add a condition to the delete service entry of the install sequence:
<InstallExecuteSequence>
<DeleteServices>NOT UPGRADINGPRODUCTCODE</DeleteServices>
</InstallExecuteSequence>
This implies to me that it is possible to retain entries across a major upgrade, but I may be misunderstanding.
Unfortunately there does not appear to be any equivalent installexecute sequence element for a SqlDatabase entity. Is there any guidance on how one should approach this?
UPDATE
Based on PhilDW's answer, changing the sequence or schedule of the major upgrade is done by changing the Schedule attribue:
<MajorUpgrade
DowngradeErrorMessage="A newer version of [ProductName] is already installed."
Schedule="afterInstallExecute"/>
Note however that this will only take you so far - if you plan to add support for trusted authentication as well as SQL authentication in your installer (as per the SO article above) it will not work, my assumption is that Wix determines that one component was never installed (whichever authentication option was not chosen) and therefore will always drop the database.
There are a few ways to address this, depending on the internals of your MSI:
A major upgrade that is sequenced at the "end", after InstallExecute and just before InstallFinalize, means that the upgrade is basically an install of the new product on top of the currently installed product. File overwrite rules apply, one of which is that data files won't be replaced if they have been updated after installation. So data files are saved. Other considerations are that binary file versions must be updated for those you need updating, and component rules must be followed.
If the issue is based on custom actions that run when the older product is being uninstalled, then you can use a custom action condition such as REMOVE="ALL" and not UPGRADINGPRODUCTCODE. UPGRADINGPRODUCTCODE is set in the older product as it is being uninstalled, not in the incoming upgrade.
I believe some WiX util types custom actions are based on the uninstall of the related component, so you wouldn't need that condition in 2. A major upgrade after InstallExecute increments the ref counts of each component (which is why you need to follow component rules) while following file overwrite rules. So your data file would have its ref count counted up to 2, would not be overwritten, then the older product uninstall would count it down to 1, so that the component remains, and an uninstall custom action based on component removal would not run.
If there is something you need to do in the upgrading install that's custom action based, then WIX_UPGRADE_DETECTED will tell you that you are upgrading an installed product.
On the upgrade link you refer to, Chris Painter's answer is the correct one. It's basically the same point that I'm making here, so of course he's correct :)

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.