Altering or removing the existing package via a minor upgrade is a good approach for fixing what's there. But ensuring this happens before your major upgrade is a quandary. You can't integrate it into a single Basic MSI package, mostly because this is not possible in Windows Installer itself. While you can add a custom action to the UI sequence, this will not work for anyone installing it silently. And you can't do anything in the execute sequence due to restrictions in Windows Installer.
If you can use a Suite/Advanced UI project, you could theoretically deliver one exe that could install the minor and then the major upgrade; I'm not sure what the hurdles are with this approach; normally the Suite isn't used to install a temporary package like the minor upgrade would be, nor does it have a clean way to automate package removal during installations.
Here are two options to help your users get where they need with the minimum confusion.
Identify, instruct, and abort
The ActionProperty of your major upgrade is filled with the product code of related packages that are present on the machine. Typically this is a single product code. If you follow the pattern of the ISPreventDowngrade entry and custom action, you can use a type 19 "error" custom action to show a message and abort the major upgrade when the older version is present. The message should instruct the user either to uninstall the older version of the product before installing the new version; or, alternately, to apply the minor upgrade and then continue.
Make the condition on the custom action as specific as possible; if you know a single product code exhibits the behavior, make your condition check for its value in the action property. If all specific range of versions exhibit this behavior (but older ones work fine), consider adding a secondary "detect only" major upgrade and condition your custom action against the secondary upgrade's action property.
Note: You can try to couple this with a UI sequence action that attempts to automate the uninstall or minor upgrade. But definitely keep the conditions in the execute sequence to ensure silent uninstallation failures get good information in the log files.
Try to ignore errors
(Whoops; after writing this, I reread where you said you've tried this approach and it doesn't work for you. So you're probably back to Identify, instruct, and abort, or perhaps using a Suite/Advanced UI project to deliver things. I'm leaving this for posterity, however, as I believe it includes good suggestions to avoid additional problems with using this option.)
I haven't used this, so I don't know the full ramifications of its behavior and I won't recommend it. But there's an option in Attributes column of the Upgrade table that allows you to ignore failures during the removal of the older version. InstallShield exposes this on the Advanced tab as Continue on Failure.
If you're 100% certain that your older version ends up in a satisfactory state, and your new version will work after this, you might try this. I would strongly recommend some thorough QA on this approach, including faking a newer major version to ensure that further upgrades still do the right thing.
Similar to the advice I gave in Identify, instruct, and abort, try to set the Continue on Failure for as few prior versions as possible. For example, you may want to split your Upgrade entries into three version ranges: those before the problem (don't continue); those affected by the problem (continue); those after the problem, i.e. future major upgrades (don't continue). This avoids hiding any similar problems that arise in the future so that you can explicitly choose how to handle them as they come up.
msidbCustomActionTypeDll + msidbCustomActionTypeBinaryData
), which in turn callLaunchAppAndWait()
on another exe. – bavazaReturn Processing: Synchronous (Check exit code)
. Is this what you mean? – bavaza