WiX Installer: how to remove old Product versions? - wix

Developer created 3 installers of the same product and changed the UpgradeCode (yes, I know, but it is).
These installers were provided to customers and some of them used these versions.
Now I have built the new installer, then added records to the msi using SuperOrca: to uninstall the old product installations with incorrect upgrade codes.
How I can do it in WiX installer project do not using SuperOrca to patch the msi every time after it is built?

Upgrade code should not change. In an installer if you are releasing another major version you can change the product code but the Upgrade code should be same of a product throughout the lifetime. Add below tags inside product tag in Wix to automatically uninstall the previous version when you install the new version-
<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>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
As OnlyDetect is set to No the wix will automatically uninstall the previous version after the InstallInitialize phase. Wix will detect the version from the range that you have mentioned as example given above-Minimum-1.0 to maximum-99.0

Many people seem to be under the impression that an upgrade can only upgrade one install and that there's something wrong with changing upgrade codes, but none of this is required. The Upgrade table in an MSI file can upgrade as many installed products as you like, as you know from using SuperOrca.
So all you need to do is add Upgrade elements naming the UpgradeCode values and range of versions you need. If there are three products that might be installed then add the three Upgrade elements naming them all. You'll end up with an Upgrade table (look in the MSI) that will turn out the same as if you added them with Orca.

Related

How to disable downgrade and enable upgrade in wix installer?

I want to remove the older version and install the latest version setup. If installing the older version means, need to restrict the downgrade.
I have enabled the upgrade and removed the older version if exist using below code.
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="{Guid}">
<UpgradeVersion Minimum="1.1.0.1" Maximum="99.0.0.0"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
<RemoveExistingProducts Before="InstallInitialize" />
But i don't know how to disable the downgrade option. I am getting solution to restrict the downgrade for 3 digit(x.x.x) version. But can get solution to restrict 4 digit(x.x.x.x) version.
There is no support in Windows Installer (and therefore in WiX generation of MSI major upgrades) for major upgrade logic based on four fields of the ProductVersion. As the docs say:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370859(v=vs.85).aspx
"Note that Windows Installer uses only the first three fields of the product version. If you include a fourth field in your product version, the installer ignores the fourth field."
The issue is that a major upgrade requires a change in the first 3 fields, so using four fields means you can't use a major upgrade of any kind. You might be able to create a custom bootstrapper that looks at installed versions and incoming upgrade versions, and it would detect attempts to downgrade, but you'd need to uninstall that older version then install the upgrade separately, and there would be recovery, no single transaction to restore the system in case of failure somewhere. The rules say three fields are used in major upgrades.

WIX: When upgrading, what to do when there are 2 different UpgradeCodes?

After getting a good answer here: WIX: How can I uninstall a previous MSI built using a VS *.vdproj, now i'm facing a different issue in the field.
I have 2 versions out there, with 2 different UpgradeCodes. That happened because we already deployed one version of the new WIX w/out syncing the UpgradeCode with the old MSI.
Syncing the new Wix installer with one of the codes, upgrade goes smoothly. Am I hosed on the second one? I tried to just uninstall the extra one from Add/Remove and that worked smoothly, but before I instruct those users to go to Add/Remove, I wanted to know if there's another trick to handle both.
Maybe if I can somehow detect during installation which version is installed, can i set the new Wix UpgradeCode dynamically?
Put both UpgradeCodes into the Upgrade table into two separate rows. This allows you to have the MSI automatically uninstall the older MSIs during an upgrade (if that's what you want), as well as give you MSI properties to use conditionally to check what's already installed on the system.
Update (to respond to the first comment)
<!-- old product -->
<Upgrade Id="$(var.UpgradeCode1)">
<UpgradeVersion Property="OLD_PRODUCT_FOUND_1"
IncludeMaximum="yes"
Maximum="2.0.0"
MigrateFeatures="yes"
OnlyDetect="no" />
</Upgrade>
<!-- new product -->
<Upgrade Id="$(var.UpgradeCode2)">
<UpgradeVersion Property="OLD_PRODUCT_FOUND_2"
IncludeMaximum="yes"
Maximum="3.0.0"
MigrateFeatures="yes"
OnlyDetect="no" />
</Upgrade>
This code will detect both UpgradeCodes, and if one (or both) are found will remove them during the RemoveExistingProducts action.
To detect the older version I would look into using a custom action.

How do you uninstall another program in wix installer?

I have lost the GUID's for my old installer. I managed to get the upgrade id using Orca but it still does not remove the old version from the programs and features list. How can I uninstall an old msi/bootstrapper with a completely new one?
If you have a MSI to uninstall (i.e. not a bootstrapper) then you should be able to uninstall it with WIX <Upgrade> element, by specifying it there like that:
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is installed." />
<Upgrade Id="{YOUR-OTHER-STUFF-GUID-HERE}">
<UpgradeVersion OnlyDetect="no" Property="OTHER_STUFF_FOUND" Minimum="0.0.0" />
</Upgrade>
If you have some EXE to uninstall, not MSI, then AFAIK only a custom action is a solution (just execute the uninstall line using custom action).
-Make use of the windows installer API: MsiEnumRelatedProducts() to get a list of all the products that share the same UpgradeCode.
https://msdn.microsoft.com/en-us/library/aa370103(v=vs.85).aspx
This API returns the product code of all the products installed on the system that share the same UpgradeCode.
You can probably see examples of the usage of this over the internet or Windows installer SDK.
Also, there was one related question recently:
WiX - Allowing a *manual* uninstall of one msi to uninstall another msi that shares the same UpgradeCode (and not just during the MajorUpgrade)
-The other approach is to upgrade your old msi package using the new msi package.
http://wixtoolset.org/documentation/manual/v3/howtos/updates/major_upgrade.html
Another way would be reading Uninstall key (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall) from registry and look for your application name / publisher and if match found execute the UninstallString command.

Wix - replacing seperate 32bit and 64-bit MSIs with one newer 32-bit MSI

Background
We have a 64 and 32 bit version of an MSI:
app.msi
app_x86.msi
these have been created with Wix and have separate upgradeCodes defined for each MSI.
We also have a WIX bundle EXE that decides on which MSI to use according to platform.
The Problem
The 64-bit version no longer exists, we want ALL upgrading clients (MSI or EXE, 32 ot 64-bit) to use the 32-bit version.
I guess I need 2 MSIs still, each with matching the old upgrade codes, 1 for 32-bit and 1 for 64-bit but will identical content....
Ideally I'd have 1 MSI have can upgrade 2 different upgradeCodes but I guess that's not possible.
I hope the above is clear.... we've tried :
- produce a single 32-bit dll (app_x86.msi)
- copy to matche the previous 64 bit (app.msi)
- ensure both MSIs have the same upgrade code as before
And yet we end up with a side-by-side install.
Adding another answer since I need code formatting. This Wix sample seems like a pretty good basic start.
I don't have this machine set up properly for testing this XML code, but something like this should work:
Upgrade table entry for X32:
<Property Id="PREVIOUSVERSION_X32" Secure="yes" />
<Upgrade Id="YOUR_GUID_X32_EDITION">
<UpgradeVersion
Minimum="1.0.0" Maximum="99.0.0" Property="PREVIOUSVERSION_X32"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Upgrade table entry for X64:
<Property Id="PREVIOUSVERSION_X64" Secure="yes" />
<Upgrade Id="YOUR_GUID_X64_EDITION">
<UpgradeVersion
Minimum="1.0.0" Maximum="99.0.0" Property="PREVIOUSVERSION_X64"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Here is a snapshot of how a similar upgrade scenario might be implemented in the compiled MSI file:
You can add several upgrade codes to the upgrade table and uninstall them as part of your install. See this sample too.
An upgrade code identifies a "family of products" (or technically a number of product codes that match the upgrade code) and each entry in the upgrade table will define a common upgrade strategy for all of the product codes that match that particular upgrade code.
In other words you can just add the two different upgrade codes to your upgrade table, author the remaining fields and this should work. You probably need two ActionProperties. Remember to add them both to the SecureCustomProperties. I believe Wix takes care of this automagically. If this isn't done the PUBLIC property values are not passed from the client to the server installation process on secure client PCs (which is most PC's with newer Windows versions) and X-files problems result. The client process runs with interactive user rights, and the server process runs with LocalSystem (full system access).

Wix/MSI - How to avoid installing same MSI twice

I have my installer coded in WiX language. It supports major upgrade mechanism. A particular requirement is that the same MSI file will not be possible to install twice.
Now comes the tricky part: if user install and then try to install it again (UI mode) the installer enters in maintenance mode and everything works OK (Change/Repair will appear disabled.)
However when installing as our use case states in silent mode
msiexec.exe /i installer.msi /qn
The second install will proceed to install as normal (we don't want this!)
Some things to noticed about are:
In the log file of the second installation the sequence "FindRelatedProducts" will be skipped (as state in microsoft documentation http://msdn.microsoft.com/en-us/library/windows/desktop/aa368600(v=vs.85).aspx)
Also I research a bit an here http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/UpgradeVersion-is-not-detecting-the-same-version-preventing-downgrades-td5875840.html there is good information, claiming that for this scenarios we can used Installed property to detect if Product is already installed...
However, I get stuck here: because I have to avoid installing previous or same versions than current one and allowing upgrades greater, How could I achieve this in WiX?
Thanks for your help!
First all, you shall fix your upgrade code:
<?define ProductVersion = "0.0.2.3"?>
<?define UpgradeCode = "PUT-GUID-HERE"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Name="Asd" Language="1033" Version="$(var.ProductVersion)" Manufacturer="Me" Id="*" UpgradeCode="$(var.UpgradeCode)">
Note that the product code is recreated each time you build the installation (by not using the GUID but the asterisk).
The fundamental information is the product version and the upgrade code. The product code identify the specific deployed release, while the upgrade code identity the product releases "family". Softwares having the same upgrade code can be switched with each other. Softwares having the same product codes cannot be installed toghether.
Here is the trick to make upgrade you software:
<Upgrade Id="$(var.UpgradeCode)">
<!-- Detect older product versions -->
<UpgradeVersion OnlyDetect="no" IncludeMinimum="yes" IncludeMaximum="yes" Minimum="0.0.1" Maximum="$(var.ProductVersion)" Property="PREVIOUSVERSIONSINSTALLED"/>
<!-- Detect newer product versions -->
<UpgradeVersion OnlyDetect="yes" IncludeMinimum="no" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED"/>
</Upgrade>
<!-- Exits successfully in the case newer version are already installed -->
<CustomActionRef Id="WixExitEarlyWithSuccess"/>
By using the above markup, you say to Wix abort installation when he find a product having the same UpgradeCode but the installed one has a Version greater than the current one, but begin the installation (upgrading the current one) if he find a product having the same UpgradeCode and the installed one has a Version less than the current one.
The IncludeMinimum and IncludeMaximum shall do the trick, allowing the upgrade to skip the current version.
Wix doesn't install the same product: you shall be sure that the product code is the same for installed software and MSI-packaged software: if they are different, they are different deployed softwares. Beyond this, if the product has the same product code of the MSI, the installation offers the repair/change options: to disable them you have to play with the Property table of the Wix package, by introducing the ARP_ variables (you can disable repair, change and uninstall, but also setup manufacturer contacts and other properties).
Here is the ARP variable list. I don't know what is their behavior when installing in silent mode, but if you are invoking msiexec from command line, there is a specific repair option to issue repair (/f), so how can it automatically repair your product if you are not requesting?
This cannot be done.
When trying to install an already installed package, Windows Installer automatically performs a repair. There is no upgrade process.
Also, the maintenance process is triggered based on ProductCode. When launching your package the second time Windows Installer sees that its ProductCode is already installed and enters maintenance mode. It's not related in any way to upgrades.
Upgrades are used only when changing the ProductVersion and ProductCode.
Edit:
To prevent an automated repair in maintenance mode you can try this:
write a win32 DLL custom action which detects if the product is installed or not
if it is, this custom action should return 1602