Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wix/MSI - How to avoid installing same MSI twice

I have my installer coded in WiX language. It supports major upgrade mechanism. A particular requirement is that the same MSI file will not be possible to install twice.

Now comes the tricky part: if user install and then try to install it again (UI mode) the installer enters in maintenance mode and everything works OK (Change/Repair will appear disabled.)

However when installing as our use case states in silent mode

msiexec.exe /i installer.msi /qn

The second install will proceed to install as normal (we don't want this!)

Some things to noticed about are:

In the log file of the second installation the sequence "FindRelatedProducts" will be skipped (as state in microsoft documentation http://msdn.microsoft.com/en-us/library/windows/desktop/aa368600(v=vs.85).aspx)

Also I research a bit an here http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/UpgradeVersion-is-not-detecting-the-same-version-preventing-downgrades-td5875840.html there is good information, claiming that for this scenarios we can used Installed property to detect if Product is already installed...

However, I get stuck here: because I have to avoid installing previous or same versions than current one and allowing upgrades greater, How could I achieve this in WiX?

Thanks for your help!

like image 545
Santi Agüero Avatar asked Oct 05 '11 03:10

Santi Agüero


People also ask

How do I change the default install location for MSI?

You can override the default installation directory by using an INSTALLDIR property in the msiexec command.

Which service is responsible for installation of MSI?

Windows Installer (msiexec.exe) is responsible for interpreting installation packages (MSI files) and installing applications.


2 Answers

First all, you shall fix your upgrade code:

<?define ProductVersion = "0.0.2.3"?>
<?define UpgradeCode = "PUT-GUID-HERE"?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

<Product Name="Asd" Language="1033" Version="$(var.ProductVersion)" Manufacturer="Me" Id="*" UpgradeCode="$(var.UpgradeCode)">

Note that the product code is recreated each time you build the installation (by not using the GUID but the asterisk).

The fundamental information is the product version and the upgrade code. The product code identify the specific deployed release, while the upgrade code identity the product releases "family". Softwares having the same upgrade code can be switched with each other. Softwares having the same product codes cannot be installed toghether.

Here is the trick to make upgrade you software:

<Upgrade Id="$(var.UpgradeCode)">
    <!-- Detect older product versions -->
    <UpgradeVersion OnlyDetect="no" IncludeMinimum="yes" IncludeMaximum="yes" Minimum="0.0.1" Maximum="$(var.ProductVersion)" Property="PREVIOUSVERSIONSINSTALLED"/>
    <!-- Detect newer product versions -->
    <UpgradeVersion OnlyDetect="yes" IncludeMinimum="no" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED"/>
</Upgrade>
    <!-- Exits successfully in the case newer version are already installed -->
<CustomActionRef Id="WixExitEarlyWithSuccess"/>

By using the above markup, you say to Wix abort installation when he find a product having the same UpgradeCode but the installed one has a Version greater than the current one, but begin the installation (upgrading the current one) if he find a product having the same UpgradeCode and the installed one has a Version less than the current one.

The IncludeMinimum and IncludeMaximum shall do the trick, allowing the upgrade to skip the current version.

Wix doesn't install the same product: you shall be sure that the product code is the same for installed software and MSI-packaged software: if they are different, they are different deployed softwares. Beyond this, if the product has the same product code of the MSI, the installation offers the repair/change options: to disable them you have to play with the Property table of the Wix package, by introducing the ARP_ variables (you can disable repair, change and uninstall, but also setup manufacturer contacts and other properties).


Here is the ARP variable list. I don't know what is their behavior when installing in silent mode, but if you are invoking msiexec from command line, there is a specific repair option to issue repair (/f), so how can it automatically repair your product if you are not requesting?

like image 85
Luca Avatar answered Oct 05 '22 21:10

Luca


This cannot be done.

When trying to install an already installed package, Windows Installer automatically performs a repair. There is no upgrade process.

Also, the maintenance process is triggered based on ProductCode. When launching your package the second time Windows Installer sees that its ProductCode is already installed and enters maintenance mode. It's not related in any way to upgrades.

Upgrades are used only when changing the ProductVersion and ProductCode.

Edit:

To prevent an automated repair in maintenance mode you can try this:

  • write a win32 DLL custom action which detects if the product is installed or not
  • if it is, this custom action should return 1602
like image 41
rmrrm Avatar answered Oct 05 '22 22:10

rmrrm