Configure WiX project to install multiple versions, but remove same minor version - wix

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.

Related

Wix Not showing Repair Option in UI

I implemented upgrade handlers and downgrade prevention
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion OnlyDetect="no" Minimum="$(var.MinimumUpgradeVersion)" Maximum="$(var.ProductVersion)" IncludeMinimum="yes" IncludeMaximum="no" Property="PREVIOUSVERSIONINSTALLED" MigrateFeatures="yes" />
<UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" IncludeMinimum="no" Property="NEWERVERSIONINSTALLED" />
</Upgrade>
And further on
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWERVERSIONINSTALLED AND NOT Installed</Custom>
<RemoveExistingProducts After="InstallInitialize">PREVIOUSVERSIONINSTALLED</RemoveExistingProducts>
However, now when I try to double-click my MSI to do a repair the UI doesn't appear anymore. I am using the same Upgrade Code so Wix should automatically allow me to repair.
Any ideas?
To do a major upgrade it might be better to use the majorupgrade element to make sure that you've included everything required. That's assuming you want a major upgrade, and I can't tell.
You are misunderstanding something. You (in WiX) use the majorupgrade element when you have a new version of your product that will replace the older one, and that includes a new ProductCode and the same UpgradeCode. This is nothing to do with repair. A repair is one of the options that can be available when you try to modify the existing installed product as defined by ProductCode, not UpgradeCode. A repair is not an upgrade or any kind of update. It repairs the existing product and will require the same MSI file that the product was originally installed from. The same UpgradeCode is nothing to do with repair.
What GUI are you including? See an online tutorial here: http://wix.tramontana.co.hu/tutorial/user-interface/ui-wizardry
Are you setting the ARPNOREPAIR property? Check in the registry at the following location (subkey, check for DWORD NoRepair):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

I have installed major upgrade successfully but it also allowing another previous version install in wix

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.

Majorupgrade or Upgrade ID which is preferred for Major upgrade?

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.

Wix: How to limit major upgrades to major version numbers?

I need the following behaviour from my wix-based installers:
Every setup in the major version 1.x.x line should majorupdate any
previous version of the 1.x.x line.
Every setup in the major version
2.x.x line should majorupdate any previous version of the 2.x.x line but
leave the 1.x.x line alone.
I though I could get this to work with the following code, but the setup removed the previous 1.x.x version. Am I mssing something? Is this even possible?
<Upgrade Id="myguid">
<UpgradeVersion OnlyDetect="yes" Minimum="2.0.0.1" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
<UpgradeVersion OnlyDetect="no" Maximum="2.0.0.1" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
You need to use a NEW GUID for 2.x if you don't want it to be "aware" of 1.x (i.e. ignore it, don't care, etc)
I use the following code, only changing var.Property_UpgradeCode when I want a new version to ignore previously installed versions (e.g. exist side-by-side in different folders)
<Product Id="*"
UpgradeCode="$(var.Property_UpgradeCode)"
Name="!(loc.ApplicationName)"
Language="!(loc.Property_ProductLanguage)"
Version="$(var.version)"
Manufacturer="!(loc.ManufacturerName)" >
<MajorUpgrade AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="!(loc.LaunchCondition_LaterVersion)"
MigrateFeatures="no"
Schedule="afterInstallInitialize" />
Put #Minimum and #Maximum attributes on a single UpgradeVersion element to specify a range. Author multiple UpgradeVersion elements to specify multiple version ranges.

Uninstalling another product during install using WiX

I want to be able to remove another application as part of the install of my MSI file. Currently, I have the following in WiX:
<Upgrade Id="{586A589B-D6D5-48D3-9B6D-571EF230ED6A}">
<UpgradeVersion Minimum="$(var.ProductVersion)"
Property="NEWERPRODUCTFOUND"
OnlyDetect="yes"
IncludeMinimum="yes" />
<UpgradeVersion Minimum="1.0.0"
Maximum="$(var.ProductVersion)"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" />
</Upgrade>
<Upgrade Id="{71F6B5D5-8CB9-48C9-B359-4BA22D5ADAF3}">
<UpgradeVersion Minimum="1.0.0.0"
Maximum="3.5.3"
Property="OLDAPPFOUND"
IncludeMinimum="yes"
IncludeMaximum="yes"/>
</Upgrade>
The first upgrade section is what upgrades my current MSI file (and this works). The second part is what I am trying to use to remove the other application (and this doesn't). Both the current MSI file and the one I am trying to remove both install in the per-machine context, so I cannot understand why this doesn't work. How can this problem be fixed?
A verbose log file should indicate what products are being detected by the Upgrade elements. From there it should be possible to track down the bug in your authoring.