Upgrade a bootstrapper bundle if the same version is detected
Asked Answered
R

5

16

I have a WiX bootstrapper bundle:

<Bundle Name="blah" Version="1.0.0" Manufacturer="blah" UpgradeCode="some-guid-string">

When I generate a new build and try to install it over a previous installation, the bootstrapper should upgrade itself (since its the same version), however it will leave the old version of itself lying around in Programs and Features. What can I do to uninstall the previous version completely if installing over the same version, and how can I remove the old build from Programs and Features? I have looked online but there aren't any clear answers on this topic.

Edit: This question hints to use a custom BA to override the default no-op behavior by changing the request state in OnPlanRelatedBundle. I'm not sure what people mean by this, or how I can hook into OnPlanRelatedBundle...can anyone clarify? Is custom BA = custom build action?

Ruy answered 27/10, 2014 at 20:34 Comment(0)
M
9

Sorry to revive an old post, but as there is still no native support for this as of WiX 3.10, I thought I would post my work-around.

The caveat to this method is that double-clicking a package that you've just installed will not bring up the usual 'modify, uninstall' dialog. What I've done to handle this is put in a <bal:Condition> which instructs the user to use 'Add Remove Programs' if they wish to invoke the uninstall or modify functionality.

The reason I need this at all, instead of just incrementing Version to perform an upgrade, is that we have online and offline bundles. I want to prevent them from being installed simultaneously.

Another thing that this approach requires is that your bundle version ID matches your MSI version ID. Enough disclaimers, here's the approach:

Create a Product search, but importantly, use the UpgradeCode for your MSI package, not for the bundles! ProductSearch will never find your Bundle's GUID because the Bundle is an .exe and not an MSI.

<util:ProductSearch
        Variable="BundleAlreadyInstalled"
        UpgradeCode="MSI-GUID-NOT-BUNDLE-GUID"
        Id="BundleAlreadyInstalledSearch"
        Result="version"
                />

Next, inside your <bundle> elements, add the following:

<Variable Name="CurrentVersionNumber" Type="string" Value="$(var.Version)" />
<bal:Condition Message="Tell your user to use Add Remove Programs here.">
    NOT WixBundleAction = 5 OR NOT BundleAlreadyInstalled = CurrentVersionNumber
</bal:Condition>

The core of the hack here is that we are using the MSI's Version (which as I said must match the Bundle's Version for this reason) as the key indicator to whether this bundle is present on the target system.

If you don't include NOT WixBundleAction = 5 you will not be able to uninstall the application, which is kind of important.

As for the second part, we want to specifically detect whether this version is already installed. Upgrades and downgrades will fail this test, which is what we want because the normal logic would kick in and perform your upgrade/downgrade.

Without this bit of logic, it was possible for my users to install both the online and offline versions of the bundle simultaneously. The primary reason for that is that the Bundle@Id is generated by WiX. Another more subtle problem that this fixes is that simply rebuilding a Bundle without modifying the Version will also allow you to install it side-by-side! You will get duplicate entries in 'Add Remove Programs' for all of these.

These problems are completely prevented by these few lines of code. As I mentioned, the trade-off is that installing, and subsequently running the exact bundle again will not trigger the uninstallation dialog, but this is a whole lot easier to live with than duplicate ARP entries. Especially since you can just provide instructions in the error message.

Molest answered 14/2, 2017 at 17:26 Comment(1)
A nice workaround. Do note that this approach does not work when you have a mba since it uses balParticipation
T
2

Try specifying a RelatedBundle Element in your Bootstrapper.

<RelatedBundle Id="THE-BUNDLE-UPGRADE-GUID" Action="Upgrade"/>
Thoughtless answered 19/2, 2015 at 11:58 Comment(0)
Y
1

v4.0 changed the default behavior to make it upgrade when it is the same version.

In v3.x, you need a custom BootstrapperApplication.

Yorgos answered 8/7, 2022 at 14:57 Comment(0)
C
0

As addressed by Sean Hall, a custom BootStrapperApplication should be introduced in V3.x of WiX to allow: 'treat same version as upgrade'. I would like to add some additional information on how this could be done within the custom BootStrapperApplication using V3.x of WiX.

Context

A bootstrapper application roughly consists of three different stages:

  1. Detection
  2. Planning
  3. Execution

Let's zoom-in to the 'upgrade' use-case with respect to these different stages. First, from the perspective of the 'new' installed bootstrapper:

  • Detection phase: a related bundle (='old' installation) is detected
  • Planning phase: the respective 'handling' of related bundle is set
  • Execution phase: a command is executed on the related bundle

Secondly, from the perspective of the 'old' installed bootstrapper:

  • Detection phase: a command is detected with the relation 'upgrade'
  • Planning phase: uninstallation is scheduled
  • Execution phase: uinstallation is executed

Implementation

We can subscribe to the respective events in the custom bootstrapper application:

connect events events

The following can be deducted from the images above:

  • We change the state in Bootstrapper_PlanRelatedBundle of the PlanRelatedBundleEventArgs to 'Present' to enforce triggering a request from the 'new' to the 'old' installation.
  • We detect if the Bootstrapper.Command.Relation has the 'upgrade' relation type and plan an 'Uninstall'. This behavior will be used to uninstall the 'old' installation, so only the 'new' installation will remain.

Source of information

Hope this helps.

Cauterize answered 6/8 at 21:25 Comment(0)
R
-1

I found a way around my problem without modifying the WiX burn source code.

I disabled my bootstrapper bundle from showing up in Programs and Features:

<Bundle DisableRemove="yes" DisableModify="yes" ... />

I didn't really need it to show up. I just needed the package it bundles and installs to show up, really. Then, I just made it show the MSI package it installed, instead:

<MsiPackage Visible="yes" ... />
Ruy answered 27/10, 2014 at 21:29 Comment(1)
You are most likely still installing duplicate bundles, you just can't see them in Add and Remove Programs...Thoughtless

© 2022 - 2024 — McMap. All rights reserved.