Skip to content

Detecting upgrade at runtime

Oleg Shilo edited this page Jan 12, 2017 · 1 revision

This content has been triggered by the Wix# user question about how to detect upgrade (but not fresh install) at runtime.

Determining if the session is an upgrade setup is not trivial. MSI as a technology is extremely convoluted and sometimes determining the state of the product and the status of the session is difficult. This task has been done in the MsiRuntime.cs. On the top of MsiRuntime.cs there is the table that maps the properties and their values to the install scenarios. You can use this table to compose the required condition that constitutes the desired setup type. Please note that the table reflects the discrepancies between MSI documentation and the actual runtime behavior.

The best way to analyse the most common MSI properties during the investigation is to build and run managed setup with BeforupeInstall event handler displaying the event arguments:

project.BeforeInstall += project_BeforeInstall;
...
static void project_BeforeInstall(SetupEventArgs e)
{
    MessageBox.Show(e.ToString(), "BeforeInstall");
}

This is what this technique produced when applied for MajorUpgrade samples:

  • Installing the product (v1.0.709.10040) for the first time

  • Upgrading the product to a newer version (v1.0.7149.10040)

    • Uninstalling previous version stage

    • Installing new version stage:

This experiment shows that the upgrade can be detected as a combination of IsModified and non empty upgrade code. This allowed to implement (in Release v1.2.0+) SetupEventArgs.IsUpgrading and Session.IsUpgrading(). The implementation under the hood is based on the following condition:

session.Property("Installed").IsNotEmpty() &&
session.Property("REINSTALL").SameAs("ALL", ignoreCase: true) && 
session.Property("UPGRADINGPRODUCTCODE").IsNotEmpty();

Or in the more readable form:

static public bool IsUpgrading(this Session session)
{
    return session.IsModifying() && session.Property("UPGRADINGPRODUCTCODE").IsNotEmpty(); 
}