WIX suppress uninstall dialog when doing a major upgrade? - wix

In one installer version of our product, I've added a custom dialog (shown by a CA using session.Message()) that asks the user if he wants to keep some of his data, at uninstall.
The CA has the condition set to REMOVE="ALL" AND NOT WIX_UPGRADE_DETECTED.
The dialog is correctly shown when doing a normal uninstall, but it also appears when removing the existing product, at a major upgrade. At that point, the installer hangs and it can only be closed from the Task Manager, resulting in an incorrect upgrade.
The installer version, containing the issue, has already been shipped.
Is there something that we can include in the next installer version (that does a major upgrade), that solves the dialog issue when removing the existing product?

The property UPGRADINGPRODUCTCODE is set in the older product as it is being uninstalled. WIX_UPGRADE_DETECTED is set in the incoming new upgrade setup when it detects.
A condition of REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE seems to be what you want, showing the dialog during unstall but not when the uninstall is because of a major upgrade.

You need to fix the cached MSI of the original version. There shouldn't be any UI during a silent installation transaction. You'll need to make a copy of the original built MSI, modify it to not execute that custom action and then recache it using msiexec /I foo.msi REINSTALL=ALL REINSTALLMODE=vomus before you can do your major uprade. Or, tell your users to do an uninstall first. This is the reason you are supposed to test your servicing strategy before you go to production. MSI is like an airplane... there is not stop or go back button. You are always moving forward and you have to plan accordingly.

Related

Only repair and uninstall can be seen while relaunching bootstrapper application

I have an msi bundled with prerequisites using Wix bootstrapper. After installing the wix bootstrapper application, if i relaunch it again i could do only repair and uninstall. But i need to have modify option also.
In MSI i tried setting the property REINSTALLMODE as "vamus". after doing so, i was able to change / repair/ uninstall w.r.t. msi.
But bootstrapper application doesn't show modify option.
On relaunching the installed wix bootstrapper application, i am expecting to have below options.
change, repair & uninstall.
A modify option makes only sense if you want to remove or add features included in an msi. May be a solution would be to set up your own bookkeeping on installed features and showing this list to the user in a custom bootstrapper application.
Another way to handle this situation may be to show the msi installation dialog which should show a "modify" dialog option.

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

Standalone WIX uninstaller

I'd like to create a standalone silent uninstaller using WIX that I can send to specific people for support purposes that can be double-clicked to execute the uninstall of our product when the uninstaller did not work properly on their machine and no longer exists (some users remove things manually using other tools). I have a .wxs file that uses the same product id and package id of the previously installed program, and if I run from msiexec /x it uninstalls the previously installed product perfectly. Double-clicking on it (which is all these users can be expected to do) however runs installation, not the uninstall. I tried adding
<Property Id="REMOVE" Value="ALL"/>
<Property Id="ACTION" Value="UNINSTALL"/>
and making sure all InstallExecuteSequence actions are not using an "Installed" check but the product is still installed after running successfully, the log file shows it is still executing ACTION INSTALL:
MSI (c) (A8:F8) [15:42:08:324]: PROPERTY CHANGE: Adding ACTION property. Its value is 'INSTALL'.
MSI (c) (A8:F8) [15:42:08:324]: Doing action: INSTALL
MSI (c) (A8:F8) [15:42:08:324]: Note: 1: 2205 2: 3: ActionText
Action 15:42:08: INSTALL.
Action start 15:42:08: INSTALL.
Is there a way to force an .msi file to perform an uninstall without using the command line or add/remove programs entries? I've seen entries about using ARPSYSTEMCOMPONENT but not enough information to do it.
I don't think so. You could, of course, use an exe to do it. I would also strongly suggest that you use the original msi file instead of creating a different msi with the same product code.
For the exe, you could use any number of chainer/bundler/downloaders. There is NSIS and also WiX's own Bootstrapper, ... even WinZip.
You should also note that many package management systems that run uninstall commands will run the install command first if anything is amiss. The theory is that an uninstaller can't properly run unless the critical data placed by installation exists. (E.G., WPKG). For Windows Installer, this usually doesn't apply since it's data is hidden from the user. But if they found it and corrupted it, reinstalling and/or repairing using a fresh copy of the original msi might do the job.

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.

Wix Major Upgrade and Install Context Issues

I have a Wix project that I have set to allow major upgrades. I'm using WixUI_Advanced for a choice between per-user and per-machine installs. When I install and upgrade per-user everything works as expected, the installer recognizes an upgrade and there is only one entry in Programs and Features. However when I choose a per-machine install, it starts duplicating entries in Programs and Features (even when both install and upgrade are per-machine and to the same folder).
Looking at the install log file it seems that FindRelatedProducts is executing before the user gets a chance to select a per-machine install, so the installer thinks that the context has changed and won't do an upgrade. I attempted to suppress FindRelatedProducts in InstallUISequence but when I do that the installer still skips FindRelatedProducts in the InstallExecuteSequence.
What are my options at this point?
You could manually execute the FindRelatedProducts action again, after the installation context was selected. Use the MsiDoAction method. I used this approach once and it seemed to work.
A better approach would be to run your own custom action before FindRelatedProducts that would search for a previous version of the product already installed. That custom action should set ALLUSERS to either 1 or to Nothing depending on the scope of that previous version, so that FindRelatedProducts finds it and schedules its upgrade. A good idea would then be to disallow selecting the per-user scope for the user if the previous version was installed per-machine - otherwise the installer may have insufficient privileges to upgrade the previous per-machine installation.
This seems to be the approach taken by InstallShield. If you create an empty test MSI package with the free InstallShield Limited Edition and then de-compile it with Dark, you will see that that custom action is called IsSetAllUsers and located in SetAllUsers.dll.