I am creating my installer msi using WIX.
My older application is already installed on machine when I am installing newer version of the application then it removes all files and assembly of older version and put newer version files and assembly but in programs and features of control panel shows both older and newer version.
I am using following code for upgrade
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="$(var.ProductVersion)" IncludeMinimum="no" OnlyDetect="yes" Language="!(loc.lcid)" Property="NEWPRODUCTFOUND"/>
<UpgradeVersion Minimum="1.0.0.0" IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" Language="!(loc.lcid)" Property="UPGRADEFOUND"/>
</Upgrade>
<CustomAction Id="PreventDowngrading" Error="!(loc.CustomAction_PreventDowngrading)"/>
<InstallUISequence>
<Custom Action="SetWindowsTypeProp" Before="FindRelatedProducts">1</Custom>
<!--Custom Action="SetPresenceProperties" After="SetWindowsTypeProp">1</Custom-->
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
</InstallUISequence>
<InstallExecuteSequence>
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
<RemoveExistingProducts Before="InstallInitialize"/>
</InstallExecuteSequence>
Please help me how to remove entry from programs and features
This means your MajorUpgrade isn't working. FindRelatedProducts isn't finding the older version and therefore REmoveExistingProducts isn't working. For recent versions of WiX you can remove a lot of this code and replace it with the newer MajorUpgrade element. It's a higher level abstraction that simplifies much of this authoring.
In order to have a successful MajorUpgrade several things have to happen:
1) Old and New MSI have to have the same UpgradeCode GUID. (Although it's technically possible for an MSI to remove unrelated Products by using additional UpgradeCode properties we'll ignore this for the purpose of this question.)
2) Old and New MSI must have unique ProductCode GUIDs.
3) New MSI must have a higher version ProductVersion property. Please note that only the first 3 numbers are evaluated. ( 1.2.3 -> 1.2.4 works 1.2.3.4 -> 1.2.3.5 does not )
4) Old MSI and New MSI must be installed in the same context ( Per User->Per User or Per Machine -> Per Machine )
5) Upgrade Table must be authored correctly. Use the MajorUpgrade element to assist in this.
I need to configure my WiX project to be able to install multiple minor versions of the product. IE: I can have 1.0, 1.1 and 1.3 installed. If I try to install 1.2, it will work, but if I try it with 1.1, it will uninstall the previous 1.1 installation before proceeding.
So far, this is what I have in my Upgrade tag:
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="$(var.MajorMinorVersion)" IncludeMinimum="yes"
Maximum="$(var.VersionNumber)" IncludeMaximum="no" Property="OLDERMINORFOUND"/>
</Upgrade>
UpgradeCode is a guid defined in my wxi file and MajorMinorVersion is the same as VersionNumber, but with the build at 0 (1.1.0 when the version is 1.1.12).
I'm guessing that I have two possibilities:
I make another UpgradeVersion tag or update the current one to have the maximum at the next minor version and exclude it from the search:
<UpgradeVersion Minimum="$(var.MajorMinorVersion)" IncludeMinimum="yes"
Maximum="$(var.NextMinorVersion)" IncludeMaximum="no"/>
Using a custom action to set NextMinorVersion somehow. Maybe using a property instead.
Or, change the UpgradeCode manually each time the minor version changes. Or have the first few characters of the guid represent the version and the rest be unique? I doubt that's a good idea though...
So basically, what would be the best way to accomplish this, in the hopes of having only one setup project for all versions?
EDIT
I've looked into the MajorUpgrade tag, but I don't think I can configure it to have many minor versions at the same time. Any light on this is appreciated.
I've also looked into making a preprocessor extension that would manipulate the version number using functions, so I could do this:
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Property="OLDERMINORFOUND"
Minimum="$(var.MajorMinorVersion)" IncludeMinimum="yes"
Maximum="$(myprefix.NextMinor($(var.VersionNumber)))" IncludeMaximum="no"/>
</Upgrade>
See my answer for details.
So I wrote an extension as per the WiX manual (Part 1 and Part 2).
I made a preprocessor extension that takes a version number string (ex: 1.2.3.4) and manipulates the version by parsing and splitting the string.
So now I can write this in my .wxs file:
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Property="SAMEMINORFOUND" OnlyDetect="no"
Minimum="$(var.MajorMinorVersion).0" IncludeMinimum="yes"
Maximum="$(version.NextMinor($(var.VersionNumber)))" IncludeMaximum="no" />
<UpgradeVersion Property="OLDERVERSIONFOUND" OnlyDetect="yes"
Maximum="$(var.MajorMinorVersion).0" IncludeMaximum="no"/>
<UpgradeVersion Property="NEWERVERSIONFOUND" OnlyDetect="yes"
Minimum="$(version.NextMinor($(var.VersionNumber)))" IncludeMinimum="yes"/>
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
Where version.NextMinor is a call to my preprocessor extension.
So my installer will only detect installations of the product unless the minor versions match, where it will be uninstalled.
I have installed major upgrade (say #206) successfully and included code as in (#206):
<Upgrade Id="$(var.ProductUpgradeCode)">
<UpgradeVersion Minimum="$(var.ProductVersion)" IncludeMinimum="no" OnlyDetect="yes" Language="1033" Property="NEWPRODUCTFOUND" />
<UpgradeVersion Minimum="1.0.0.178" IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" Language="1033" Property="UPGRADEFOUND" />
</Upgrade>
Scenario is:
I have installed build #177 then upgraded to build #206. It is still allowed to install #177 which I want to prevent this downgrade.
From build #178 onward I have changed product GUID for major upgrade and which is working fine.
Please suggest how to prevent this. I don't want to downgrade build below 177. If I have done major upgrade on build no <= 177.
Your problem is the how the comparison of versions is done in MSI by default - 1.0.0.123 is treated the same as e.g. 1.0.0.33. You either have to increase your revision version to make the installer detect this as an older version or use a workaround.
You might for instance create a custom action to check against this very Revision version and place it e.g. before InstallValidate:
<CustomAction Id='MyVersionCheck' Return='check' (...) />
<InstallExecuteSequence>
<Custom Action='MyVersionCheck' Before='InstallValidate' />
</InstallExecuteSequence>
Some more information can be found in this article, for informations about how to create custom actions i'd recommend this blog entry as a starting point.
We are trying to do Major upgrade. While i was investigating i found 2 approaches.
One is using Upgrade Id and another one approach was Majorupgrade tag.
It seems Majorupgrade is easy to do it seems. But schedule doesn't contain any before installinitialize action.
I am not sure which should be using .
Which one is preferred [and recommended] mostly?
The MajorUpgrade element was introduced in wix 3.5 to simplify what you would normally do with the Upgrade element. So that instead of something like this:
<!– Major upgrade –>
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="$(var.ProductVersion)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED" />
<UpgradeVersion Minimum="1.0.0" IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate" />
</InstallExecuteSequence>
<Condition Message="Can't downgrade">
NOT NEWERVERSIONDETECTED
</Condition>
You can simply do this:
<MajorUpgrade DowngradeErrorMessage="Can’t downgrade." />
Not only is the old way more verbose, it also requires that you repeat the upgrade code and product version which are specified in the Product element. So the sample above has to make use of wix variables to keep them in sync. If you get that wrong, the upgrade won't work correctly.
The new MajorUpgrade element has none of those complications, so I recommend that you use it. See also this blog post by Bob Arnson introducing MajorUpgrade and the topic in the wix documentation on the subject.
We use wix to create our setups. For upgrading, we use major upgrades as demonstrated in this answer by Rob Mensching. (In newer wix versions you can use the MajorUpgrade element.) This normally works well. The old product is removed, then the new product is installed.
However, apparently the above is not completely equivalent to manually uninstalling the old product and then manually installing the new product.
Consider for example the following scenario:
version 1.0 of our product is released, containing version 5.0 of a thirdparty dll
version 1.1 of our product is released, containing version 5.1 of the same thirdparty dll
version 1.2 of our product is released, downgrading to version 5.0 of the thirdparty dll again because we discovered that the new version introduced more problems than it solved.
Apparently with the wix upgrade logic linked above, the 3rdparty dll will disappear when upgrading from release 1.1 to 1.2. A repair is necessary to restore it.
Is there another way to upgrade, which would work for this scenario? I guess what I am looking for is upgrade logic which allows the downgrading of components, by behaving exactly as if one manually uninstalls the old product and then manually installs the new product.
We also encountered this problem where lower-versioned DLLs were not getting reinstalled on a major upgrade. I thought it was strange that the installer would decide which files to install based on the versioning of existing files, then completely uninstall everything, but still only install what what files had been determined to install before uninstalling the old product. This seems like it might be a bug in Windows Installer...
To fix this problem we moved the RemoveExistingProducts action above the CostFinalize action.
I know the documentation on MSDN recommends placing the RemoveExistingProducts afterInstallValidate, and I'm not sure if putting it before the InstallValidate action has any negative side effects for minor upgrades, but we have decided to only perform major upgrades for our products so this solution appears to work for us.
Behaviors like this generally have to do with the sequencing of RemoveExistingProducts. If it occurs late enough, Windows Installer will have figured out that there's a newer version of the .dll on the machine, so version 1.2 doesn't need to install it. However when the RemoveExistingProducts results in removing the .dll, nothing puts it back.
Things to try including changing the sequencing of RemoveExistingProducts, and lying about the version of the .dll in your 1.2 package (report a version number higher than the bad one). The downside of the latter is poor impacts on repairs or patching, as the .dll always looks out of date.
Try to schedule RemoveExistingProducts earlier, right after InstallValidate, and change the value of REINSTALLMODE property to amus. This way the old product will be completely removed before any files from the new product are copied, and a mode will force re-install of the files.
It's sub-optimal, but I fixed the same problem by renaming the third party dll and changing the GUID on the component node associated with it in the .wxs file.
Years later, this thread helped me in the right direction. An example for completeness with RemoveExisitingProducts moved before costing:
<Upgrade Id="UPGRADE-GUID-HERE">
<UpgradeVersion OnlyDetect="no" Property="UPGRADABLEFOUND"
Maximum="$(var.ProductVersion)" IncludeMaximum="yes" />
<UpgradeVersion OnlyDetect="yes" Property="NEWERFOUND"
Minimum="$(var.ProductVersion)" IncludeMinimum="no" />
</Upgrade>
<InstallExecuteSequence>
<Custom Action="NoDowngrade" After="FindRelatedProducts">NEWERFOUND</Custom>
<RemoveExistingProducts Before="CostInitialize" />
</InstallExecuteSequence>
<CustomAction Id="NoDowngrade" Error="A newer version of $(var.ProductName) is already installed." />
Here's my final solution based on the answer given by #Spacemani.
It produces MSI table entries (Upgrade, LaunchCondition etc.) similar to this
<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeErrorMessage)" />
but gives you full control of the InstallExecuteSequence.
<!-- Product upgrade -->
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion OnlyDetect="no" Property="WIX_UPGRADE_DETECTED"
Maximum="$(var.ProductVersion)" IncludeMaximum="no" IncludeMinimum="no"
MigrateFeatures="yes" />
<UpgradeVersion OnlyDetect="yes" Property="WIX_DOWNGRADE_DETECTED"
Minimum="$(var.ProductVersion)" IncludeMinimum="no" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts Before="CostInitialize" />
</InstallExecuteSequence>
<Condition Message="!(loc.DowngradeErrorMessage)">NOT WIX_DOWNGRADE_DETECTED</Condition>
Note that you need to suppress ICE27 errors in your .wixproj file like this.
<PropertyGroup>
<SuppressIces>ICE27</SuppressIces>
</PropertyGroup>