WIX upgrade scenario - wix

I have an existing WIX installer file that I'm trying to figure out. In this file I see two custom actions defined:
<Custom Action="CreateBackup" Before="InstallInitialize">
<![CDATA[Installed]]>
</Custom>
<Custom Action="RestoreBackup" After= "InstallFinalize">
<![CDATA[NOT Installed]]>
</Custom>
The CreateBackup function copies some files (not directly related to this installer) from a remote location. Restore puts those files back at the same location.
Now in an upgrade scenario I see the following logging order. I have put the apparent value of "Installed" in brackets:
CreateBackup is skipped (Installed == false)
InstallInit
CreateBackup succeeds (Installed == true)
InstallInit
InstallFinalize
RestoreBackup is skipped (Installed == true)
InstallFinalize
RestoreBackup succeeds (Installed == false)
I have a couple of questions about this:
I understand that there is an uninstall and an install going in this script. And based on the value of "Installed" I conclude that the install is done first. Is this correct?
I see that the InstallInit is called twice before the first InstallFinalize. What does this mean? Is the installation still busy when uninstall begins?
The first value of Installed is false, so I guess it is relative to the new version? But how does it become false again after the deinstallation finishes? Is it relative to the old version then?
I am using an MajorUpgrade element.
Hope someone can clear this up.

I'm assuming that you are using a WiX MajorUpgrade element to do your upgrade, so the conditions you need should be something like this:
When you are doing an upgrade the WIX_UPGRADE_DETECTED property is set when an upgrade is being done:
http://wixtoolset.org/documentation/manual/v3/xsd/wix/majorupgrade.html
So use that condition when you want to create the backup, assuming that you want to do the backup of existing files (from the older product) when doing the upgrade.
It's not clear from your post exactly when you want to do the restore but if it's after the upgrade then use the same WIX_UPGRADE_DETECTED property.
Those conditions based on the Installed property don't seem to make a lot of sense because the property is set if the current MSI's ProductCode is installed. In a upgrade at that stage it will always be unset.
This post has more info about properties and install actions:
How to add a WiX custom action that happens only on uninstall (via MSI)?

Related

Can we apply transform(.mst) while uninstallation?

We found some uninstallation issue on already released msi which is creating issue during upgrade of higher version.I need to modify few custom action conditions so that it doesn't run while msi uninstallation. In order to this, transform file is generated with updated condition. However, I am not sure how to pass this during uninstallation? user can trigger uninstall from Add or Remove Programs.
Minor upgrades are not option for us as it requires release of new msi.
The locally cached MSI within the Windows folder is a transformed version of your original MSI database, if you installed it together with the MST.
Your custom actions added by MST, if they have no condition set, are always run (on install, repair and removal).
If you want to run your action only on uninstallation, set this as the condition: REMOVE="ALL" or inverted NOT REMOVE="ALL" if it should NOT run on uninstallation.
Try to place your custom action in the Table InstallExecuteSequence between InstllValidate and InstallInitialize or after InstallFinalize
You don't need the MST during uninstallation.

Wix toolset Bundle Chain installation global condition

CONTEXT: I created a Bootstrapper installer in order to install, if needed, the .net framework 4.8. together with the setup program I want to deliver with it.
Up to here all works nice: my program gets installed always and the .net just if needed.
The thing is that I need to add some more checks to this installer, for example check for a registry key (if another program proper version is installed) and if this does not meet the condition, then the complete installation should be aborted, nothing should be installed.
PROBLEM: the InstallCondition I have added affects just the MsiPackage but the rest of the installation seems to be considered as totally fine and installation finishes successfully, here the interesting part of code:
<util:RegistrySearch Id="OtherProgramVersionId" Root="HKLM" Key="SOFTWARE\XXX\Install::Version" Variable="OtherProgramVersion"/>
<Chain>
<PackageGroupRef Id="NetFx48Redist" />
<MsiPackage
Id="MySuperProgram.Setup"
SourceFile="$(var.MySuperProgram.Setup.TargetPath)"
InstallCondition="OtherProgramVersion >= v10.0"/>
</Chain>
As said before, even the registry key is not found or it does not fulfill the condition, the installation seems to continue "successfully" and I get it in the ControlPanel->Programs as installed... but the main .msi was not really installed! (checking the destination folder, it's empty)
QUESTION: How can I add a global condition in order to stop completely any installation at all and show the user a message with the condition not fulfilled? If possible with a standard dialog.
I have seen (and I am still experiencing) with conditions, but seems they affect just one of the items in the chain... or they seem to break the installation somehow, I have tried adding to the .msi setup creation, file Product.wxs, the condition in order to abort this installation, but when installing I get this not passed condition as a setup error, seems the exit is not clean at all... even able to see the log where I see something like this:
Error 0x80070643: Failed to install MSI package.
Thanks in advance!
If you're using WixStandardBootstrapperApplication, you can use bal:Condition to define bundle-level conditions. The WiX documentation has a sample: https://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/block_stdba_install_on_reg.html

Uninstall msi with full ui mode condition (wix toolset)

I've added the following to my WIX template to prevent installation without entering values in a custom dialog i've made.
<Condition Message='This installation can only run in full UI mode.'>
<![CDATA[UILevel = 5]]>
</Condition>
When I try to uninstall the application I get this message, and I'm unable to proceed.
How do I fix this so that it does not apply on uninstall?
How can I forcibly uninstall this application?
Question 1: LaunchCondition
LaunchConditions must always evaluate to true for the setup to be able to install / run. There are some further details here: Failing condition wix (recommended for more context). When you invoke uninstall via Add / Remove Programs it will run the installer in silent mode (I believe UILevel = 2 or UILevel = 3), which fails your LaunchCondition since UILevel is not equal to 5.
OR Installed: A common technique to prevent LaunchConditions to trigger problems in other installation modes than fresh install, is to add OR Installed to the LaunchCondition in question. This will force the LaunchCondition to be true for all situations and modes where the product is already installed (modify, uninstall, repair, etc...).
So something like this could probably work as an updated condition:
Installed OR UILevel = 5
Wrong Approach?: With that said I would rather implement a check to determine if the value you need specified has been set on the command line via PUBLIC properties for a silent install, instead of that rather strange LaunchCondition checking the setup's GUI level. You can still implement this as a LaunchCondition - or use a custom action for more flexibility. The LaunchCondition would check for values for all critical setup parameters, and you would prevent them from running on uninstall and other modes with the OR Installed mechanism. Here is an answer on the topic of silent installation, transforms and public properties: How to make better use of MSI files (silent deployment is crucial for corporate deployment and software acceptance).
Question 2: Forcibly Uninstall
UPDATE: A couple of additional options listed towards the bottom for completeness.
2.1 - ARP Modify: I want to run the simplest option by you before going into too much crazy detail. Is the Modify option available for your setup in Add / Remove Programs? If so, please click it and see if you then can select remove from the setup's Modify dialogs. This should work (since you are generally not running the setup in silent mode when choosing Modify).
2.2 - Interactive msiexec.exe Uninstall Command: I forgot to add that you should be able to kick off an interactive uninstall via command line as follows: msiexec.exe /x {PRODUCT-GUID} /qf. Here is how you can find the product GUID: How can I find the product GUID of an installed MSI setup? So in summmary: you find the product GUID as explained in the link, and then you open a cmd.exe window and fire off the uninstall command indicated above.
2.3 - Microsoft FixIt: If the first option above is not available, there are several other options that could work, but before trying them I would recommend giving the Microsoft FixIt tool for installation / uninstallation problems a chance to see if this does the trick for you. Run it, select your installation and see if some auto-magic is there for you to get it uninstalled.
2.4 - Advanced (avoid if you can) - hack system-cached MSI: This answer will be the next step, if the above fails: I screwed up, how can I uninstall my program? Please let us know if the above does not work, and we will check the options here. I would just zip up the cached MSI and disable the launch condition, but this is way too hacky for comfort if you can avoid it.
UPDATE: The below was added, but not needed to solve the problem. It is not recommended, it is the last resort. Leaving the content in.
Finding Cached MSI: you can find the system cached MSI using Powershell as explained here. I will inline the Powershell command here:
gwmi -Query "SELECT Name,LocalPackage FROM Win32_Product WHERE
IdentifyingNumber='{PRODUCT-GUID}'" | Format-Table Name,
LocalPackage
You then open the cached file (make a backup of it first, or zip it) with Orca or an equivalent tool, and you make whatever change needed to get the uninstall to function correctly. This is not generally considered a sane approach - it is the last resort. And what you change in the MSI is different depending on what is wrong with it. This requires specialist MSI knowledge. It is easy to mess things up so uninstall becomes even more difficult.
I just saw you got the product uninstalled whilst writing this. Puh! Be glad you don't need this latter approach. I think I will commit it and set it to strikeout so it is visible but not recommended (if only for myself to reuse if needed).
UPDATE, some additional alternatives (not always applicable, included for reference and potential re-use): 1) If you have access to the original MSI used to install your software (it must be the exact copy of the MSI used to install), then you can try to double click it and this should take you into modify directly. 2) You can also double click the file in the system cache folder if you no longer have the original installation MSI. 3) It might be you can hotfix the uninstall string in the registry as well to force a non-silent uninstall:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall
There are probably further ways. For example 4) hack a transform to apply during uninstall, 5) patch the installed MSI (if it is in the wild with lots of installs everywhere), etc...

Avoid uninstall when WiX AllowSameVersionUpgrades is Yes?

I have the WiX's Product Id="*" and AllowSameVersionUpgrades="yes", so I can have 1 installer with different features (different sample images, but same .exe).
And I want to be able to install the multiple versions in the same machine so only the new features are added and the old features remain in the folder. But the old features are always being deleted. Is there a way to handle the correct way, maybe using Custom Actions?
For anyone with a similar problem the solution I've found was create a property:
<Property Id="DELFILES" Secure="yes"/>
Secure="yes" is very important otherwise the property's value won't be read when running the installer.
And then add this condition for the custom action:
<![CDATA[(REMOVE = "ALL") AND (DELFILES = "TRUE")]]>
Finally to install I just call the .msi and pass the parameter:
MsiExec.exe /x MyInstaller.msi DELFILES="TRUE"

Conditional uninstall of previous version in Wix

I'm doing an installer for an software used for debugging embedded ARM cores (OpenOCD) and this installer automatically removes the previous versions - that's simple. However, sometimes that would be desirable to have more than just one version installed (each version has it's own folder, so there's no conflict here) due to various (in-)compatibility issues etc.
I'm trying to create an installer which would have an option in the Feature tree (or anywhere else) to uninstall (or not) the previous version.
Basically there is this install sequence:
<InstallExecuteSequence>
<Custom Action="NewerVersionDetected" After="FindRelatedProducts">DOWNGRADE</Custom>
<RemoveExistingProducts After="InstallFinalize"/>
</InstallExecuteSequence>
I know that RemoveExistingProducts can be made conditional by putting a condition between RemoveExistingProducts tags but... what should the condition be? There's a lot of info about making features conditional or about conditions like OS version and some registry entries, but I haven't found any useful info about "user-defined conditions"...
Let's say that in the feature tree there is this element:
<Feature Id="UninstallOlderVersionFeature" Title="Uninstal previous versions" Level="1" Description="..."/>
How to make uninstallation previous version conditional on this feature (or any other method the user could select during the installation - a question box or a separate window or whatever it takes)?
Any help appreciated (by me and the users of the installer), as I'm not very good in Wix and XML (I'm an embedded person (; )
If any more details on the whole Wix file are required - tell me and I'll post relevant bits.
Try this:
<RemoveExistingProducts After="InstallFinalize">
<![CDATA[&UninstallOlderVersionFeature=3]]>
</RemoveExistingProducts>
It is the state wether the feature is selected. "3" says that the Feature is selected for installation.