Wix 3.6: Conditionally trigger "RemoveExistingProducts" - wix

I crawled the web but found no solution or I just got not the clue.
I need to conditionally perform the RemoveExistingProducts action in my setup. I want my setup to uninstall all existing products by default, like this:
<MajorUpgrade AllowDowngrades="no" DowngradeErrorMessage="No downgrades allowed" />
This works fine. But when the user deselects a checkbox in my UI I want the installer NOT to uninstall previous product version. So I tried something like this:
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="3E700BA7-CAF8-4C49-A53A-70F70DE0C8D6">
<UpgradeVersion
Minimum="1.0.0.0" Maximum="99.0.0.0"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" OnlyDetect="myVar" />
</Upgrade>
<Property Id="myVar" Value="no" />
hoping, that I can set the myVar, but this is illegal.
Has anybody an idea how to solve my problem?
The reason is, that we want to allow the users - at their own risk - to have more than one version of our product installed - this is a request by our customer.

I think, in the default sequence, RemoveExistingProducts is run before the UI.
You could try rewiring the RemoveExistingProducts action to be after InstallFinalize and trigger it with a condition:
<RemoveExistingProducts After="InstallFinalize">
NOT CHECKBOX
</RemoveExistingProducts>
Not sure how this would fare in your case.
You could also try running a custom action when you exit the dialog with your checkbox to manually uninstall the product. Maybe you could even force the launch of RemoveExistingProducts in said custom action.
One last solution would be to make a separate uninstaller that prompts the user to uninstall the product or not and follow up with the actual installer.

Related

For Wix Toolset and UpgradeVersion tag is Property ever reset

We have the code below for our Product.wxs.
When the installer is run we can see afterward that BackupFiles custom action runs, but RestoreFiles does not run as shown in the log file:
"Skipping action: RestoreFiles (condition is false)"
Why does BackupFiles, with same condition, run and RestoreFiles not run?
Has the OLDVERSIONFOUND been changed?
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" >
<Product Id="*" Name="My Product" Language="1033" Version="0.0.0.0" Manufacturer="MyCompany"
UpgradeCode="{B55B9CB0-BA28-4BB3-834B-6075AD5D45E4}">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<UIRef Id="WixUI_ErrorProgressText" />
<!-- Specify UI -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALL_FOLDER" />
<Property Id="RestoreFiles" Value="INSTALL_FOLDER" />
<Upgrade Id="{B55B9CB0-BA28-4BB3-834B-6075AD5D45E4}">
<UpgradeVersion Minimum="1.0.0"
IncludeMinimum="yes"
OnlyDetect="no"
Maximum="0.0.0.0"
IncludeMaximum="no"
Property="OLDVERSIONFOUND" />
</Upgrade>
<InstallExecuteSequence>
<Custom Action="BackupFiles" After="InstallValidate" >OLDVERSIONFOUND</Custom>
<Custom Action="SetRestoreFiles" Before="RestoreFiles" />
<Custom Action="RestoreFiles" After="InstallFiles" >OLDVERSIONFOUND></Custom>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
</Wix>
Custom actions like these are not really recommended. They can be quite complicated to get right. See links towards the bottom on "settings preservation".
The short version is that settings files should never be installed, but created by the application from defaults or templates (then the setup will never interfere with them), or you can cloud all settings and retrieve on launch from a database. See here, section "cloud-style approaches".
Major Upgrades - Uninstall & Install: There is an important weirdness with major upgrades. You have to remember that you kick off the new installer, and then it will kick of the old installer's uninstall sequence as part of its own operation. Hence a major upgrade will run the uninstall sequence of your old setup and the install sequence of your new setup (potentially in different orders based on configuration of the major upgrade settings).
Counter-Intuitive Effects: This combined "install / uninstall" approach affects logic, conditioning, sequencing and also property values a great deal - and some changes are very counter-intuitive. In addition to two different versions running "at the same time" (or during the same operation), you must also keep in mind that the each installation / uninstallation sequence runs in two different modes: immediate (building execution script) and deferred (executing script executing). With poor conditioning the same custom action could run several times unexpectedly (including in the GUI sequence of the launched setup). Confusing. Debug using message boxes as described towards the bottom here.
Detailed Explanation: This complexity and the phenomenon of property values seemingly changing during installation is attempted explained in detail here: Run Wix Custom action only during uninstall and not during Major upgrade - please read that answer (dual source and all). I will look back later, it is too late for me to run tests tonight.
Throwing in some further links:
On settings preservation
Overview on settings preservation
"Property Debugger" - on how to test property values
"Property Debugger" - another version

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

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.

Uninstall shortcut in WiX when Product Id is * to allow major upgrades?

I was following the tutorial here to implement an uninstall shortcut in the start menu.
In short, the way to create the uninstall entry is as follows:
<Shortcut Id="UninstallProduct"
Name="Uninstall My Application"
Target="[SystemFolder]msiexec.exe"
Arguments="/x [ProductCode]"
Description="Uninstalls My Application" />
Based on Rob Mensching's suggestion here, if the application is small enough and you don't need to handle small updates and minor upgrades (which I don't), you can force every update to be a major upgrade. This is shown here. I used Rob's suggestion which was this:
<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>
Now my question is if Product Id is randomized (*) to allow a major upgrade to take place, is there any other way to add an uninstall shortcut to the start menu or must we do it through Add/Remove programs? I'd prefer to create the shortcut in the start menu since it's just easier for the user. Obviously the way it is now, it won't work because [ProductCode] that is used in the msiexec arguments will change on every install. Thanks.
Are you saying you've tried it and it doesn't work? How does it fail? What is the shortcut argument? Using Product/#Id="*" sets the ProductCode property, so it should work correctly.

Uninstallation problem

When program is installed it is fired(by the installer) right after installation finishes. But when i uninstall the program from Control Panel, then it tries to open the exe too, which gives the following error:
Windows cannot find 'MyExe.com'. Make sure you typed the name correctly, and then try again. To search for a file, click the Start button, and then click Search.
with the cmd.exe in the background.
after i press OK, another window pops up, saying:
There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support...
Although the program gets uninstalled, these errors are not desirable.
Also when i install newer version and older version of the program already exists, i get similar messages as the installer tries to uninstall older version first.
Here is the code:
....
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="D2B0D435-0F86-4D5E-A988-B24215882***">
<UpgradeVersion
Minimum="1.0.0.0" Maximum="99.0.0.0"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
<CustomAction Id="LaunchApp" Directory="INSTALLDIR" ExeCommand="[SystemFolder]cmd.exe /C start MyExe.exe" />
<InstallExecuteSequence>
<RemoveExistingProducts Before="InstallInitialize" />
<Custom Action="LaunchApp" After="InstallFinalize" />
</InstallExecuteSequence>
</Product>
</Wix>
What i would like, is that installer would try to run the program only when installation occurs and do nothing when uninstallation is processed.
Thanks in advance!
Your problem is that you don't have a condition on the action so it fires every time. At a minimum you need a condition of "Not Installed". However for a more elegant solution, read:
How To: Run the Installed Application After Setup