75

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?

Ajay
  • 18,086
  • 12
  • 59
  • 105
EddieD
  • 916
  • 2
  • 9
  • 10

5 Answers5

112

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>
Mike Fuchs
  • 12,081
  • 6
  • 58
  • 71
  • is not there, Please advice. I use wix 3.8 with VS 2013. I think the structure of .wxs file is different there – Kushan Randima Sep 25 '15 at 07:45
  • Not sure what you mean with "not there". But do you have your file defined (see the fragment with )? – Mike Fuchs Sep 25 '15 at 08:05
  • Nice answer. I recommend further reading: http://wixtoolset.org/documentation/manual/v3/howtos/updates/major_upgrade.html http://wixtoolset.org/documentation/manual/v3/howtos/general/generate_guids.html and https://support.firegiant.com/entries/24013876-Implement-major-upgrade- – anhoppe Oct 27 '15 at 14:52
  • I have the same issue with the !(bin.FileVersion.MyAssemblyDll) i have added the file to the fragment & componentgroup. I copied exactly the same thing you posted, What is 001_MyAppliaction? this is never defined? – vanlooverenkoen Jan 31 '17 at 18:55
  • 1
    @KoenVanLooveren: You need to replace MyAssemblyDll and the path to it with your own project specific information (in my example, 001_MyApplication.MyAssembly would be a project name in the same solution). Note that this is only a suggestion how to keep incrementing the version (binding it to a version of your assembly that does auto-increment). To test, you can also just ignore all of this and write ``. Please read section 2 again, and have a look at [wix variables](http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html). – Mike Fuchs Feb 01 '17 at 13:43
  • 3
    Finally someone who actually explains how WIX works. The documentation fails utterly. Changing the product ID to `*` worked for my case. – QuantumHive Aug 15 '17 at 09:15
  • Wix can learn from this answer, this trumps their documentation. – Andy Clark Nov 26 '20 at 21:32
  • What is !(bind.FileVersion.MyAssemblyDll)? Is there any documentation on this? – john k Oct 11 '21 at 14:54
  • @johnktejik Have a look at https://wixtoolset.org/documentation/manual/v3/overview/light.html, search for `Binder Variables`. You may also want to check out [this answer](https://stackoverflow.com/a/50613333/385995) for additional example code. – Mike Fuchs Nov 10 '21 at 22:53
39

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...

Daren Thomas
  • 67,947
  • 40
  • 154
  • 200
  • 1
    For those new to variables (the `$(var.property)` syntax that is); http://wix.sourceforge.net/manual-wix2/preprocessor.htm – Patrick Apr 25 '12 at 11:57
  • Heh, this was the exact way I had my install going. Then, I noticed I ended up with an item in Control Panel Programs for every install. I tried using a fixed Product Id which led me to Googling this answer. Combined with Randy Eppinger's comment (must increment at least the 3rd digit of the version) you get the best of both worlds. – John Hoven Oct 24 '12 at 17:23
  • Please note this solution won't work if you have multiple project files (.wxs) files. Wix tool (light) will complain about duplicate Upgrade codes (GUID). I used 'MajorUpgrade' to get around this issue – Jayee Jul 28 '16 at 06:53
9

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

Klaus Gütter
  • 11,151
  • 6
  • 31
  • 36
coding Bott
  • 4,287
  • 1
  • 27
  • 44
3

I tried this and it worked for me.

  1. Put your product tag like this:

    Product Id="*" Name="Something" Language="1033" Version="1.0.0.0" Manufacturer="Someone" UpgradeCode="43ab28d7-6681-4a05-a6b5-f980733aeeed"

Product Id should be set to * so that every time you build your project, it takes different id.

  1. Nest a MajorUpgrade tag inside your Package element which looks like:

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

So, every time you update your version(or your version is same, not less than current version), it reinstalls your product by removing the previous files and installing the product files. It will not downgrade your product.

-3

Just put this element under the Product element:

<MajorUpgrade AllowDowngrades="yes" />

More info in this HowTo

Gian Marco
  • 22,140
  • 8
  • 55
  • 44