How to implement WiX installer upgrade?
Asked Answered
A

12

250

At work we use WiX for building installation packages. We want that installation of product X would result in uninstall of the previous version of that product on that machine.

I've read on several places on the Internet about a major upgrade but couldn't get it to work. Can anyone please specify the exact steps that I need to take to add uninstall previous version feature to WiX?

Animadversion answered 22/9, 2008 at 10:34 Comment(0)
P
218

In the newest versions (from the 3.5.1315.0 beta), you can use the MajorUpgrade element instead of using your own.

For example, we use this code to do automatic upgrades. It prevents downgrades, giving a localised error message, and also prevents upgrading an already existing identical version (i.e. only lower versions are upgraded):

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />
Petrinapetrine answered 26/8, 2010 at 13:57 Comment(12)
Bob Arnson's blog post about this provides a lot of nice information.Rufous
Note: Not documented anywhere, but the "<MajorUpgrade>" element must be placed after <Package>. Otherwise, candle gives the following error: "error CNDL0107 : Schema validation failed with the following error at line 1, column 473: The element 'Product' in namespace 'schemas.microsoft.com/wix/2006/wi' has invalid child element 'MajorUpgrade' in namespace 'schemas.microsoft.com/wix/2006/wi'. List of possible elements expected: 'Package'.".Darton
+1 This answer needs to receive as many upvotes as possible; it's very tempting to go with an answer that has 5x the upvotes, but uses older approaches.Kraken
Good point. I've added an example so that people don't ignore it just because it doesn't have one!Petrinapetrine
Just want to point out you don't need to specify AllowDowngrades or AllowSameVersionUpgrades. They default to no already.Prizewinner
True. I wanted it to be obvious to anyone else reading my particular piece of code, but of course that won't be the case for everyone!Petrinapetrine
I've changed it to the accepted answer since it's better than my original findingsAnimadversion
Hopefully this won't resurrect an old thread, but I feel a couple of additional things could be mentioned for creating a "newer" version: 1) You need to increment one of the first three digits of the "Product Version" attribute. 2) Change the GUID in "Product UpgradeCode". 3) Put an actual GUID in "Package Id" attribute (as opposed to the recommended asterisk), and keep that constant across versions. WIX coughs up a huge warning for the GUID, but it won't work as an upgrade otherwise.Bastard
My previous comment is wrong - ignore it. What I described does not complain when installing, it doesn't upgrade like I thought. Put an asterisk in "Product Id". Put an actual GUID in "Product UpgradeCode" - and NEVER change this. Put an asterisk in "Package Id". Finally, when you increment the numbers in "Product Version", it'll do an actual update.Bastard
Tried this and got "another version of this product is already installed"Buhr
Same as AriesConnolly, another version of this product is already installed errorEpicontinental
My understanding is that you get that error when you've recompiled your setup program without increasing the version number. You can set the AllowSameVersionUpgrades attribute to yes, but that comes with its own problems...Petrinapetrine
A
234

Finally I found a solution - I'm posting it here for other people who might have the same problem (all 5 of you):

  • Change the product ID to *
  • Under product add The following:

    <Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
    <Upgrade Id="YOUR_GUID">  
       <UpgradeVersion
          Minimum="1.0.0.0" Maximum="99.0.0.0"
          Property="PREVIOUSVERSIONSINSTALLED"
          IncludeMinimum="yes" IncludeMaximum="no" />
    </Upgrade> 
    
  • Under InstallExecuteSequence add:

    <RemoveExistingProducts Before="InstallInitialize" /> 
    

From now on whenever I install the product it removed previous installed versions.

Note: replace upgrade Id with your own GUID

Animadversion answered 22/9, 2008 at 13:3 Comment(25)
Seems this question is much more popular then I thoughtAnimadversion
yes, learning WiX is like trying to figure out the obscure incantations that someone decided 'made sense' to perform a simple action. Kind of like UNIX.Fumarole
Hm, I suspect that I shouldn't use that particular GUID in the "Upgrade Id=", but will have to match it so something else. But what?Caduceus
Also you may have to tweak the UpgradeVersion Min and max - e.g. If your current version is less than 1.0Caduceus
Also, what exactly does "Change the product ID to *" do? Does it generate a new product Id each time? Are there consequences to your product not having a fixed Id any more? - it sounds like overkill.Caduceus
@Caduceus - yes using * will cause it to generate a new product ID each time. I found that for the "automatic upgrade" to work I need a new product Id for each version and this is the simplest way to do soAnimadversion
We need to know the ID so generate (manually) a new ID for each public release. Using the same ID for all internal betas. Works OK but you can't autoupgrade between betas which is OK for usFreshet
@Antony, @Dror Helper: I'm pretty sure you should not be using "*" to generate a new GUID here. The GUID inside (Upgrade Id="") should be hard-coded and fixed, and it should match the GUID in your (Product UpgradeCode="") attribute.Ruffina
By which I mean, don't use "*" in the upgrade Id, but do, of course use it in the product Id as Dror intended.Ruffina
note that this will remove any version installed, even if it is newer than the one you are trying to installGelatinoid
I think you should probably edit your example there to NOT have an actual GUID. I'm sure people will copy-and-paste that and use it verbatim. Maybe use "YOUR-PRODUCT'S-UPGRADECODE-GUID-HERE"?Registered
There is bug in your example. MSI's ProductVersion only supports three version fields; therefore the fourth field will not be compared at all. See the note under VersionMin and VersionMax in msdn.microsoft.com/en-us/library/aa372379(VS.85).aspxPiglet
For wix2, Product ID should be "????????-????-????-????-????????????" instead of "*"Piglet
Although the upgrade seems to work using the method above, in "Add Remove Programs" I still see the old version (and of course the new one). Any ideas why that happens and how I can really delete the old version?Delwyn
Using this technique, do I still need to change the UpgradeCode between releases?Delwyn
This helped me too, turns out the PREVIOUSVERSIONSINSTALLED is really important, even though nothing appears to be using the property...Inexistent
I've done exactly what was suggested, but this isn't working for me. If I run my newer install, it simply ignores the existing installation and installs a fresh copy. What kind of things might I be missing?Biologist
I don't seem to have an InstallExecuteSequence element... (scratching head).Pagano
@Pagano Are you sure you're placing InstallExecuteSequence in the right parent? I've made that mistake a few times alreadyLeakey
Why isn't there a "DontCareJustCopyTheFiles" element?Antigorite
@DrorHelper Is it possible to remove(uninstall) more than one product using wix during the installation of msi created by wix. Plese look into my SO question and guide me #26863794Doth
I'm not sure, I haven't done WIX in a while - I think you should write a question instead of a comment so that other users can help you.Animadversion
I assure you @mmr, packaging on Linux is a lot simpler.Rundle
Please note that this solution won't work if WIX installer has multiple project files and if you are trying to build the project with msbuild.Commonweal
@Fumarole I wish there was an option to bookmark comments. WiX is driving me nuts for several days now and all I want to implement is a simple upgrade scenario.Witha
P
218

In the newest versions (from the 3.5.1315.0 beta), you can use the MajorUpgrade element instead of using your own.

For example, we use this code to do automatic upgrades. It prevents downgrades, giving a localised error message, and also prevents upgrading an already existing identical version (i.e. only lower versions are upgraded):

<MajorUpgrade
    AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
    AllowSameVersionUpgrades="no"
    />
Petrinapetrine answered 26/8, 2010 at 13:57 Comment(12)
Bob Arnson's blog post about this provides a lot of nice information.Rufous
Note: Not documented anywhere, but the "<MajorUpgrade>" element must be placed after <Package>. Otherwise, candle gives the following error: "error CNDL0107 : Schema validation failed with the following error at line 1, column 473: The element 'Product' in namespace 'schemas.microsoft.com/wix/2006/wi' has invalid child element 'MajorUpgrade' in namespace 'schemas.microsoft.com/wix/2006/wi'. List of possible elements expected: 'Package'.".Darton
+1 This answer needs to receive as many upvotes as possible; it's very tempting to go with an answer that has 5x the upvotes, but uses older approaches.Kraken
Good point. I've added an example so that people don't ignore it just because it doesn't have one!Petrinapetrine
Just want to point out you don't need to specify AllowDowngrades or AllowSameVersionUpgrades. They default to no already.Prizewinner
True. I wanted it to be obvious to anyone else reading my particular piece of code, but of course that won't be the case for everyone!Petrinapetrine
I've changed it to the accepted answer since it's better than my original findingsAnimadversion
Hopefully this won't resurrect an old thread, but I feel a couple of additional things could be mentioned for creating a "newer" version: 1) You need to increment one of the first three digits of the "Product Version" attribute. 2) Change the GUID in "Product UpgradeCode". 3) Put an actual GUID in "Package Id" attribute (as opposed to the recommended asterisk), and keep that constant across versions. WIX coughs up a huge warning for the GUID, but it won't work as an upgrade otherwise.Bastard
My previous comment is wrong - ignore it. What I described does not complain when installing, it doesn't upgrade like I thought. Put an asterisk in "Product Id". Put an actual GUID in "Product UpgradeCode" - and NEVER change this. Put an asterisk in "Package Id". Finally, when you increment the numbers in "Product Version", it'll do an actual update.Bastard
Tried this and got "another version of this product is already installed"Buhr
Same as AriesConnolly, another version of this product is already installed errorEpicontinental
My understanding is that you get that error when you've recompiled your setup program without increasing the version number. You can set the AllowSameVersionUpgrades attribute to yes, but that comes with its own problems...Petrinapetrine
E
91

The following is the sort of syntax I use for major upgrades:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" Version="$(var.ProductVersion)">
 <Upgrade Id="PUT-GUID-HERE">
    <UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
    <UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>

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

As @Brian Gillespie noted there are other places to schedule the RemoveExistingProducts depending on desired optimizations. Note the PUT-GUID-HERE must be identical.

Effy answered 7/4, 2009 at 4:5 Comment(7)
I'm reading the "Upgrading and Patching" section in Nick Ramirez' book on Wix here, and he states that if you schedule RemoveExistingProducts after InstallInitialize, then you MUST also schedule <InstallExecute After="RemoveExistingProducts" />. Your example does not have this - does that mean the book is wrong?Hustings
I never explicitly schedule InstallExecute.Effy
Out of interest, what do you do for minor upgrades?Bismarck
I don't. In WiX v3.6, Burn will make minor upgrades easy to execute but without Burn it requires manual interaction from the user (have to provide command-line options) that makes Minor Upgrades basically useless. :)Effy
@RobMensching: how do you avoid the installation of an older version over a newer one? Your answer works for me (the only "major upgrade" example that I can get to compile at all with WiX v3.5.2519.0), but it's possible to install an older version (after that, I see both versions in "Add/Remove Programs").Seward
Okay, I just found the MajorUpgrade element in this answer which does exactly what I want, including preventing downgrades.Seward
@RobMensching Is it possible to remove(uninstall) more than one product using wix during the installation of msi created by wix.I am able to upgrade the previous version with new one using wix but i need to unintall other 2 appliction also during this upgrade. Plese look into my SO question and guide me #26863794Doth
N
40

The Upgrade element inside the Product element, combined with proper scheduling of the action will perform the uninstall you're after. Be sure to list the upgrade codes of all the products you want to remove.

<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="00000000-0000-0000-0000-000000000000">
  <UpgradeVersion Minimum="1.0.0.0" Maximum="1.0.5.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>

Note that, if you're careful with your builds, you can prevent people from accidentally installing an older version of your product over a newer one. That's what the Maximum field is for. When we build installers, we set UpgradeVersion Maximum to the version being built, but IncludeMaximum="no" to prevent this scenario.

You have choices regarding the scheduling of RemoveExistingProducts. I prefer scheduling it after InstallFinalize (rather than after InstallInitialize as others have recommended):

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

This leaves the previous version of the product installed until after the new files and registry keys are copied. This lets me migrate data from the old version to the new (for example, you've switched storage of user preferences from the registry to an XML file, but you want to be polite and migrate their settings). This migration is done in a deferred custom action just before InstallFinalize.

Another benefit is efficiency: if there are unchanged files, Windows Installer doesn't bother copying them again when you schedule after InstallFinalize. If you schedule after InstallInitialize, the previous version is completely removed first, and then the new version is installed. This results in unnecessary deletion and recopying of files.

For other scheduling options, see the RemoveExistingProducts help topic in MSDN. This week, the link is: http://msdn.microsoft.com/en-us/library/aa371197.aspx

Neither answered 18/10, 2008 at 5:56 Comment(2)
@Brian Gillespie: what does "...if there are unchanged files..." mean? What is the criteria for Windows Installer to decide when to replace a file, AssemblyVersion, AssemblyFileVersion, file size,...?Tops
@Tops +1 learnt this the hard way. RemoveExistingProducts was scheduled to after InstallFinalize and dlls were not being updated as assemblyVersion was unchanged but other fields like AssemblyProduct were. I dont want to be at the mercy of the file comparison routine - i just want the previous app GONEOrthodontist
R
16

You might be better asking this on the WiX-users mailing list.

WiX is best used with a firm understanding of what Windows Installer is doing. You might consider getting "The Definitive Guide to Windows Installer".

The action that removes an existing product is the RemoveExistingProducts action. Because the consequences of what it does depends on where it's scheduled - namely, whether a failure causes the old product to be reinstalled, and whether unchanged files are copied again - you have to schedule it yourself.

RemoveExistingProducts processes <Upgrade> elements in the current installation, matching the @Id attribute to the UpgradeCode (specified in the <Product> element) of all the installed products on the system. The UpgradeCode defines a family of related products. Any products which have this UpgradeCode, whose versions fall into the range specified, and where the UpgradeVersion/@OnlyDetect attribute is no (or is omitted), will be removed.

The documentation for RemoveExistingProducts mentions setting the UPGRADINGPRODUCTCODE property. It means that the uninstall process for the product being removed receives that property, whose value is the Product/@Id for the product being installed.

If your original installation did not include an UpgradeCode, you will not be able to use this feature.

Rocky answered 22/9, 2008 at 13:14 Comment(2)
No doubt Mike knows exactly what he is talking about, all due respect, but it makes me sigh with despair to contemplate cluttering my mind with a firm understanding of what the Windows Installer is doing. Before I know it, I'll be doing Java and .NET consulting jobs to Enterprise clients out in the godawful tech centre towns, out beyond the ring-road, filling my TPS reports and wondering why life seems so empty. I think my next project might install with NSIS, which for all its faults, like a preposterous assembly-like language, it didn't make me understand what Windows Installer is doing.Ruffina
@Tartley - go with InnoSetup, that'll save you the assembly-like language :) Make sure you grab IStool too, it helps a lot. Also -- agreed that for simple installs all this is way too complicated, but I think they really need this complexity for installing something like SQL Server 2008...Devol
T
11

I used this site to help me understand the basics about WiX Upgrade:

http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization

Afterwards I created a sample Installer, (installed a test file), then created the Upgrade installer (installed 2 sample test files). This will give you a basic understanding of how the mechanism works.

And as Mike said in the book from Apress, "The Definitive Guide to Windows Installer", it will help you out to understand, but it is not written using WiX.

Another site that was pretty helpful was this one:

http://www.wixwiki.com/index.php?title=Main_Page

Tautomerism answered 24/9, 2008 at 15:56 Comment(1)
The example on the page does not work as expected wix.tramontana.co.hu/tutorial/upgrades-and-modularization/… . I played with it. It is even possible to downgrade when page states that it will be prohibitedWhoop
V
11

I read the WiX documentation, downloaded examples, but I still had plenty of problems with upgrades. Minor upgrades don't execute uninstall of the previous products despite of possibility to specify those uninstall. I spent more that a day for investigations and found that WiX 3.5 intoduced a new tag for upgrades. Here is the usage:

<MajorUpgrade Schedule="afterInstallInitialize"
        DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." 
        AllowDowngrades="no" />

But the main reason of problems was that documentation says to use the "REINSTALL=ALL REINSTALLMODE=vomus" parameters for minor and small upgrades, but it doesn't say that those parameters are FORBIDDEN for major upgrades - they simply stop working. So you shouldn't use them with major upgrades.

Verisimilitude answered 16/12, 2011 at 12:19 Comment(0)
E
7

I would suggest having a look at Alex Shevchuk's tutorial. He explains "major upgrade" through WiX with a good hands-on example at From MSI to WiX, Part 8 - Major Upgrade.

Eugeniaeugenics answered 22/9, 2008 at 10:34 Comment(1)
Thanks for the link to that article...it's fantastic!Arola
M
7

One important thing I missed from the tutorials for a while (stolen from http://www.tramontana.co.hu/wix/lesson4.php) which resulted in the "Another version of this product is already installed" errors:

*Small updates mean small changes to one or a few files where the change doesn't warrant changing the product version (major.minor.build). You don't have to change the Product GUID, either. Note that you always have to change the Package GUID when you create a new .msi file that is different from the previous ones in any respect. The Installer keeps track of your installed programs and finds them when the user wants to change or remove the installation using these GUIDs. Using the same GUID for different packages will confuse the Installer.

Minor upgrades denote changes where the product version will already change. Modify the Version attribute of the Product tag. The product will remain the same, so you don't need to change the Product GUID but, of course, get a new Package GUID.

Major upgrades denote significant changes like going from one full version to another. Change everything: Version attribute, Product and Package GUIDs.

Marcelmarcela answered 24/12, 2010 at 10:52 Comment(2)
Package:Id type:AutogenGuid description: The package code GUID for a product or merge module. When compiling a product, this attribute should not be set in order to allow the package code to be generated for each build. When compiling a merge module, this attribute must be set to the modularization guid. ---- so we don't need pay attention on the package id, right?Photooffset
Your link is deadKremlin
B
5

I'm using the latest version of WiX (3.0) and couldn't get the above working. But this did work:

<Product Id="*" UpgradeCode="PUT-GUID-HERE" ... >

<Upgrade Id="PUT-GUID-HERE">
  <UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
     Minimum="1.0.0.0"  IncludeMinimum="yes"
     Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>

Note that PUT-GUID-HERE should be the same as the GUID that you have defined in the UpgradeCode property of the Product.

Bilingual answered 9/3, 2010 at 7:57 Comment(0)
M
3

Below worked for me.

<Product Id="*" Name="XXXInstaller" Language="1033" Version="1.0.0.0" 
    Manufacturer="XXXX" UpgradeCode="YOUR_GUID_HERE">
<Package InstallerVersion="xxx" Compressed="yes"/>
<Upgrade Id="YOUR_GUID_HERE">
    <UpgradeVersion Property="REMOVINGTHEOLDVERSION" Minimum="1.0.0.0" 
        RemoveFeatures="ALL" />
</Upgrade>
<InstallExecuteSequence>
    <RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>

Please make sure that the UpgradeCode in Product is matching to Id in Upgrade.

Marquismarquisate answered 4/12, 2015 at 22:52 Comment(0)
F
1

This is what worked for me, even with major DOWN grade:

<Wix ...>
  <Product ...>
    <Property Id="REINSTALLMODE" Value="amus" />
    <MajorUpgrade AllowDowngrades="yes" />
Finitude answered 24/3, 2014 at 19:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.