Detect side by side installations? - wix

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.

Related

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

Remove Patched Product on Wix Bundle Uninstall

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.

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.

Option to start uninstall if application is installed

I have my application set up to only allow one install. If the application is already installed wix nicely pops up with this message
Is there a way to give the user the option to uninstall the application at this time? I don't want my users to then have to go to menu -> app -> uninstall or control panel. I would like to make it easy for them to remove the old version and install the new one.
That message is a feature of Windows Installer - it's just the way everything works, based on the fact that the product's ProductCode and PackageCode are present on the system. Since that message comes from Windows (not WiX) there is no tailoring it to install the MSI file that prompted it.
You can't have the same ProductCode installed more than once per-system install, so an option to install another MSI with the same ProductCode doesn't exist unless you make it a minor update by installing an updated version of the MSI file with an update command line.
The way you make it easy to upgrade is to use the WiX MajorUpgrade tag. You also need to increment ProductVersion in the first 3 fields, have a new ProductCode, keep the same UpgradeCode, and decide where you want the upgrade sequenced, and that depends on whether you increment file versions for updated files, and preserve component IDs for the same resources. This installs the new product while uninstalling the older one. This standard automatic major upgrade doesn't say "do you want to upgrade to this new product?". It just does it, the assumption being that people are in fact pretty smart and they are well aware that they have a new version of an installed product and that this will upgrade it. The upgrade is also a fresh install for people who don't have any old versions installed.

How to update Windows installer package over installed msi with same product id

I have created a wix installer project which is working fine. It installs my application on system easily. whenever if there is any change in any file or service, i uninstall msi from controk panel and installs new msi on system.
But whenever i install new msi, application's all setting change after new installation, that doesn't sound good. For sort out this, i am using Upgrade code in Product.wxs file. But when i install new msi after build, but is shows given error:
Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel
So, i want to update windows application package whenever there is any change in files and with same Product id. I just want to update installed msi, dont want to remove that.
You cannot use the same ProductId to do upgrades, you need to change it. The best way is to set ProductId="*" and this will change it for every build. You will also need to increase the version number and this best done by using the main exe assembly version number. See http://wix.sourceforge.net/manual-wix3/major_upgrade.htm for more info.
You can use the same ProductCode to update an installed MSI. Basically you increment the ProductVersion, rebuild the MSI (with new PackageCode) and do a minor update with a command line such as:
msiexec /i <path to new msi> REINSTALL=ALL REINSTALLMODE=vomus.
In my experience this not commonly used because if you're going to rebuild the MSI you may as well upgrade with a major upgrade.
If all you want are updates to a few files and you're not ready to ship a complete MSI file, then that's what patches are for. Rebuild the MSI as above, then build a patch - the patch is the delta between the two MSI files, see docs for MsiMsp.exe.