Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Wix to update a previously installed version of a program

I wrote an install program with Wix and it worked fine to install my program. Now I need to update it, so I bumped up the version number but when I go to install the new program over the old one it complains that an older version is already installed and tells me to uninstall it first.

How do I get it to update or automatically uninstall it before reinstalling?

like image 390
EddieD Avatar asked Feb 01 '09 12:02

EddieD


People also ask

Is WiX a installer?

WiX is a set of tools that allows you to create Windows Installer-based deployment packages for your application. The WiX toolset is based on a declarative XML authoring model. You can use WiX on the command line by using the WiX tools or MSBuild.


3 Answers

I feel that none of the provided answers are complete or self-contained, so after digging my way through this swamp, here's the steps I think are necessary to get the (utterly self-evident) requirement of an update to work:

  1. Make sure your Product Id changes every time you build. If you don't, you'll always get the "already installed" message the OP mentioned.

    <Product Id="*" ...>
    
  2. Change the Product Version every time the product itself changes. I suppose the best option is to bind it to an assembly version (which should be auto-incremented as well), but of course you could also just change it manually. This step is not strictly required if you use the AllowSameVersionUpgrades attribute in point 4, but I'd venture to say that keeping your product version constant is bad practise in any case.

    <Product Version="!(bind.FileVersion.MyAssemblyDll)" ...>
    <File Id="MyAssemblyDll" Name="$(var.001_Application.MyAssembly.TargetFileName)" Source="$(var.001_Application.MyAssembly.TargetPath)" />
    
  3. Keep your UpgradeCode constant (e.g.):

    <Product UpgradeCode="f4d7f199-28f6-45d5-ad99-7c62938274be" ...>
    
  4. Add the MajorUpgrade element (from Wix 3.5.1315.0). To circumnavigate the catch that the MajorUpgrade will disregard changes in the revision number of the product version, add the AllowSameVersionUpgrades (or if you prefer AllowDowngrades) attribute. This way, you will be able to upgrade from e.g. 1.0.0.7 to 1.0.0.8. and not just from 1.0.7.0 to 1.0.8.0. If you don't do this, you may see multiple installations in Programs and Features.

    <MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
    

Here's my whole .wix file (relevant parts, the two fragments that lead to the assembly which is used for product binding are mostly optional and for illustration, any way you can get a hold of the assembly will work):

<?xml version="1.0" encoding="UTF-8"?>
<?define ProductVersion="!(bind.FileVersion.MyAssemblyDll)"?>
<?define UpgradeCode="f4d7f199-28f6-45d5-ad99-7c62938274be"?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">
  <Product
    Id="*"
    Name="My Product's name"
    Language="1033"
    Version="$(var.ProductVersion)"
    Manufacturer="My company"
    UpgradeCode="$(var.UpgradeCode)"
    Codepage="1252">

    <Package
      InstallerVersion="200"
      Compressed="yes"
      InstallScope="perUser"
      Description="My product description"
      Manufacturer="My company"
      Languages="1033"
      SummaryCodepage="1252"
      InstallPrivileges="limited" />

    <MajorUpgrade AllowSameVersionUpgrades="yes" 
                  DowngradeErrorMessage="A newer version of [ProductName] is already installed. If you are sure you want to downgrade, remove the existing installation via Programs and Features." />

  </Product>

  <Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="LocalAppDataFolder">
        <Directory Id="INSTALLFOLDER" Name="My Install Dir" >
          <Component Id="INSTALLFOLDER" Guid="f6ba8a12-6493-4911-8edd-dce90e1d8e8b" >
            <RemoveFolder On="both" Id="INSTALLFOLDER"/>
            <RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]" Type="string" Value="My Registry value" />
          </Component>
        </Directory>
      </Directory>
    </Directory>
  </Fragment>

  <Fragment>
    <ComponentGroup Id="ProductComponents" >
      <Component Id="ProductComponent" Guid="1939f0f5-19f6-498b-bf95-8f1c81501294" DiskId="1" Directory="INSTALLFOLDER" >
        <File Id="MyAssemblyDll" Name="$(var.001_MyApplication.MyAssembly.TargetFileName)" Source="$(var.001_MyApplication.MyAssembly.TargetPath)" />
      </Component>
    </ComponentGroup>
  </Fragment>
</Wix>
like image 107
Mike Fuchs Avatar answered Oct 21 '22 08:10

Mike Fuchs


I checked through all the posts mentioned above and still spent ages trying to get this to work.

The hint on the official HOWTO for upgrades in Step 3 helped a lot: You need a new Product/@Id to disable the message "Another version of this product is already installed".

I used this upgrade section (child of Product):

<Upgrade Id="$(var.UpgradeCode)">
  <UpgradeVersion Minimum="1.0.0"
                  IncludeMinimum="yes"
                  OnlyDetect="no"
                  Maximum="$(var.Version)"
                  IncludeMaximum="no"
                  Property="PREVIOUSFOUND" />
</Upgrade>

Note that OnlyDetect is set to "no". This triggers the removal of the old version, if you have the following section (child of Product):

<InstallExecuteSequence>
  <RemoveExistingProducts After="InstallInitialize"/>
</InstallExecuteSequence>

Also note that apparently, only the first three components of the version number are used to check for upgrades...

like image 39
Daren Thomas Avatar answered Oct 21 '22 09:10

Daren Thomas


You need to use the upgrade table:

<Upgrade Id='15E2DAFB-35C5-4043-974B-0E342C25D76A'>
    <UpgradeVersion Property='OLDVERSIONFOUND' IncludeMinimum='no' Minimum='0.0.0.0' />
</Upgrade>

You need also add an action:

<InstallExecuteSequence>
    <LaunchConditions After='AppSearch' />
    <RemoveExistingProducts After='InstallValidate' />
</InstallExecuteSequence>

Here is a tutorial

like image 9
coding Bott Avatar answered Oct 21 '22 09:10

coding Bott