Remove Patched Product on Wix Bundle Uninstall - wix

I have a bundle which installs two products: the application and a much larger resources installation.
For upgrades the application msi will apply a standard upgrade, but the resources installation gets patched instead. (Unfortunately this process started a while ago, so the patch chain is still built using Wix 3.0).
On uninstall of the bundle the application is fully and correctly uninstalled, but the patch only is removed, leaving the full install of whatever previous version of the resources existed (downgrade from 1.5.0.0 to 1.4.0.0).
Is there a method to force a full uninstall of the full product, rather than just the .msp patch, through the bundle?
Edit: Just to add, exposing the resources installation in Programs and Features and running an uninstall there will remove the entire product correctly as expected.

I think this could be a possible solution for you.
I just tested myself a very simple bundle with one MSI in it. What I did was have the main bootstrapper installer have the msi embedded in it an install it. The second bundle had a higher version and the exact same msi reference but I set compressed="no" in the <MsiPackage> tag. When I uninstalled the upgraded bundle it also removed the original MSI.
So I think you can get your bundle to properly remove the original "Resources" installation after you've upgraded and added a small msp. You just need to add back the <MsiPackage> to the bundle chain before the msp and set compressed="no"
<MsiPackage SourceFile="$(var.ResourcesInstaller.TargetPath)" Compressed="no"/>
The only caveat here is that the SourceFile should be the exact same msi that was included in your first install. When you install the upgrade, the burn engine should detect this msi as already installed so nothing would be needed to be done. When uninstalling, it will detect the msi as installed and should uninstall it.
I'm not completely sure this will work but it is something to try. Another nice thing about this is it will have virtually no impact on the size of your upgrade installers.

Related

Detect side by side installations?

We want to introduce a managed bootstrapper application that detects our software products that are already installed on the target machine and then gives options to install, update, downgrade, repair and uninstall. This works well with using the same UpgradeCode in the packages.
Our issue is with side by side installations: The software is supposed to be allowed to be installed side by side if the version is not within the same “Major-Release”. Therefore, we planned to change the UpgradeCode with each new “Major-Release”.
Now the question: What is the best way to detect the side by side installations, of packages that are not within the Bundle of the current Bootstrapper? Or is there a better alternative to install side by side without changing the UpgradeCode?
The bundle handles upgrade both at the bundle and at the MSI level. The MSI level upgrade or side-by-side install is handled by how the MSI package is written and what Upgrade code it uses. From what I understand from your question, if the MSI has a new Major-Release then you want to do a side by side install and if not you want to do an upgrade.
The easiest solution that I can think of is to change your Bundle upgradecode when there is a Major-Release. But as always with side-by-side install this will complicate things and there will be multiple bundles with multiple upgrade codes that you will have to manage.
For example, you installed MSI 1.0.0.0 with bundle upgradecode "abc". When a new MSI 1.1.0.0 comes, you will use the same bundle with "abc" and do an install. This will uninstall the MSI 1.0.0.0 and install 1.1.0.0.
When the MSI 2.0.0.0 comes along you will change the bundle upgrade code, "xyz". This will install the new MSI 2.0.0.0 (provided they have changed the upgradecode within the MSI). Now at this point if you have a new MSI 1.3.0.0 you have to make sure to change your bundle upgradecode back to "abc" before you can install 1.3. Hope you got the gist of the issue/complexity that I am talking about. Side-by-side install is always a problem when you want to handle upgrades and given a choice I will stay away from it.
Now another option that you have is to handle multiple MSI releases within the same bundle. If you know the upgradecode of the new major release then you can do a product search based on the Upgradecode and then decide whether you want to uninstall the existing version and install the new version or just upgrade the existing version.
<util:ProductSearch Id="ProductSearch"
UpgradeCode="{ProductC_MSI_UpgradeCode_GUID}"
Variable="ProductInstalled"
Result="state"/>
You can use the variable ProductInstalled to check if that product/upgrade code is already present and then do the changes within your bundle accordingly.

Removing an MSI package in a bundle without including the source

I have a WIX Bootstrapper Burn bundle which contains 4 MsiPackages and has been released in production. Our latest version of the bundle is to no longer ship one of the packages and should uninstall the package should it exist. What is the best way to uninstall the MsiPackage without providing the entire msi in the bundle?
I have tried:
Removing the PackageGroup from the chain entirely - This leaves the product behind.
Adding the MsiPackage and setting the installlevel to 0 - This needs a very large payload as the msi that is being removed is large.
I also tried using product search to find the state
<util:ProductSearch Id="AppX" UpgradeCode="XXXXXX-XXXX-XXXX-XXXX-XXXXXXXX" Result="state" Variable="APPXSTATE" />
but tried to hook it up to an ExePackage to run msiexec /x UpgradeCode but I figure is the wrong way to uninstall.
Whats the best way for me to purge msi with UpgradeCode X if it exists in this newer burn installer?
Thanks
Note: I am not aware of any auto-magic constructs to use in collaboration with util:ProductSearch to uninstall existing MSI
installations.
Upgrade Table: I assume the four different products have different upgrade codes "per family"? If so - and if you are positive it will never need to be installed again - then I suppose you could specify that it should be uninstalled via a major upgrade for one or more of the packages you will keep delivering. Note: It might be possible to uninstall even if all setups share the same upgrade code, but that requires a lot more care and testing.
This solution involves adding the upgrade code for the MSI you want to remove to the upgrade table of those MSI setups you want to preserve with a version range specified that will uninstall all "known prior editions". Technical details for how to do this can be found here: Adding entries to MSI UpgradeTable to remove related products. As stated it is enough to do so for one of the products that will remain, but you can do it for all of them to be sure. No errors should result if the product has already been uninstalled. I might want to set a tighter range than what is shown in that technical sample for the versions targeted.
ExePackage: It should be possible to uninstall as you have suggested by using an ExePackage instead. It could run msiexec.exe directly I suppose, or maybe launch a VBScript, Powershell script or even a batch file or your own EXE file compiled from C++ or C# (the latter with unfortunate runtime requirements). I have never tried this approach.
Please note that you do not uninstall by upgrade code in the fashion you do with msiexec.exe /x UpgradeCode - at least I have never been able to make that work (not tested for a while). Instead you need to uninstall via product code (How can I find the product GUID of an installed MSI setup?), OR you can use VBScript and MSI API automation to uninstall by using the Installer.RelatedProducts function and then kicking off uninstall that way as shown here: Powershell: Uninstall application by UpgradeCode. This is similar to what happens when Windows Installer processes the Upgrade Table. All releated products - those sharing the same upgrade code - are enumerated and you can handle them as you do so.
Some Links:
Powershell: Uninstall application by UpgradeCode
WIX (remove all previous versions)
Wix upgrade goes into maintenance mode and never does upgrade

Can an MSI remove bootstrapper entry in Control Panel?

I have a bootstrapper that only wraps one MSI. I might prefer to give the MSI to customers who I know have already run the bootstrapper and have the prerequisites installed. But running the MSI leaves the original entry in Control Panel alongside the new one, even though the UpgradeCode code is the same for Bundle and Product.
I understand there are some issues here - the bootstrapper is not the MSI, and in fact may contain more than one MSI. So I imagine this is actually expected behavior.
Is what I want to do just considered a bad idea? Should customers who install with a bootstrapper always upgrade with a bootstrapper?
If you don't upgrade a bundle with another bundle, the old bundle's registration (more than just an ARP entry) and package cache is left behind. So yes, standard behavior is to upgrade with a newer bundle. If you are just trying to save download bandwidth, you can distribute an uncompressed bundle (just the bundle .exe with no embedded packages); only the necessary payloads will be downloaded and you won't waste bandwidth downloading prerequisites that are already installed.

WiX installer - how can I remove installed application and re-install it at the same run

I have a custom installer based on WiX technology which is install several .vsix packages into Visual Studio.
If this packages are already installed, the installer offers to remove them. After the removal process is completed, the installer exits.
It's normal behaviour, but I need to offer the user re-install this packages (optionally) before exit. I mean optional mode to uninstall the previous version and install the new one (or the same) with a single run of the installer.
How to implement this in WiX ?
I suspect your custom installer could be made a little smarter. There are plenty of APIs (such as MsiQueryProductState) that will tell you if that exact ProductCode is installed, and ways to get the version (MsiGetProductInfo). My guess is that your custom installer is just firing off all the MSI installs without checking if they are already installed, hence the Remove prompts.
Your general plan should be to have some data available to your custom installer that it can use to find out what's already installed and what the versions are, and then compare these with what you are about to install. Use those APIs. If the product is already installed then skip the install. If you have a newer version (that you built with the WiX MajorUpgrade element) then just install it because it will replace the existing older one.
There's nothing I can think of in WiX that would automatically reinstall a product that your custom installer caused removal of by re-installing it and prompting the user to remove it, if that's what's going on.

How can I upgrade installer WIX bootstrapper bundle via MSI and vice-versa?

The situation:
I have a WIX-based bootstrapper installer, which installs my msi package and (some) prerequisites (.NET). The installer is .exe and it works ok.
Now, some clients want to install msi, especially in corporate environments where they can push it centrally.
It looks easy, just give them the msi. Again, It works ok.
Now, the problematic part.
When the application is installed from MSI, and later upgraded to newer version from .exe installer, there will be two ARP entries. And vice-versa - when the application is installed from .exe, and later upgraded from MSI, there will be double ARP entries again.
Is there any easy/standard solution?
To maintain the visibility as Bundle: visible, MSI: not visible, you can either:
Install the upgrade the same way that the bundle does, passing ARPSYSTEMCOMPONENT=1 to msiexec, or
Change your MSI Product so that it defaults to not visible: <Property Id="ARPSYSTEMCOMPONENT" Value="1" />
(In your bundle, MsiPackage/#Visible seems to effectively be "no", which is the default.)