had few doubt regarding customAction
<Custom Action='CustomActionId.StopService2' After='CustomActionId.StopService1>REMOVE</Custom>
so will this REMOVE flag enables this action to run my custom action only on uninstall or both Upgrade/Uninstall/Repair/Reconfigure
Windows Services: Windows services should not be controlled or installed via custom actions, but by means of built-in MSI mechanisms: ServiceInstall, ServiceControl. These WiX elements map to the corresponding MSI tables and they support everything a normal service needs to install correctly. It is very reliable when done right. The various ways used (and abused) to install Windows Services (few are recommended).
WiX Service Example: Here is a good example of how to install a Windows service properly with MSI / WIX:
https://github.com/rstropek/Samples/tree/master/WiXSamples/WindowsService
REMOVE: As to the property REMOVE. It will be set during several MSI operations: modify, remove, upgrade. During full uninstall it will be set to REMOVE=ALL, in other scenarios it is set to a feature list which will be affected during the maintenance operation. Conditions are hard. Here is an older answer on conditions.
Major Upgrade: Keep in mind that during a major upgrade operation there is both an uninstall of the old version and an install of the new version happening. REMOVE will be set in the version being uninstalled, but generally not in the version being installed.
If you want to skip the action during a major upgrade you could try: (REMOVE~="ALL") AND (NOT UPGRADINGPRODUCTCODE) as explained in this answer. Here is a longer answer on conditions and their permutations.
Condition Debugging: You can debug conditions by using VBScripts to show message boxes during installation as explained here (towards bottom). This can help a lot to take out the guesswork. Just run the setup and show message boxes for when your custom actions run - I guarantee you there will be surprises. Conditions can reach a state when such debugging is necessary. See this example.
Related
I have a custom action that has to execute only during install but not during minor release upgrade and remove?
I tried with different conditions but the CA is executing during minor release.
1) (NOT Installed) OR NOT(REMOVE="ALL" AND UPGRADINGPRODUCTCODE)
2) (NOT Installed)
3) (NOT Installed) OR NOT(Installed AND REMOVE="ALL" AND UPGRADINGPRODUCTCODE)
but nothing works for me.
And my CA is executing twice may be because during upgrade the setup is uninstalling and installing.
Any suggestions how to execute CA only during install but not during upgrades.
Please Test: You could try with (NOT Installed) AND (NOT WIX_UPGRADE_DETECTED) as a first test (see this answer), and then use the debugging approach below to test properly. No guarantees! Conditions are notorious.
A commonly used way to test if you are running uninstall as a part of major upgrade is to use the UPGRADINGPRODUCTCODE property.
You should be aware of these issies with regards to UPGRADINGPRODUCTCODE - it might not behave as you would expect at face value.
I suggest using WIX_UPGRADE_DETECTED instead of UPGRADINGPRODUCTCODE in the above condition to keep it as simple as possible. This is a WiX-specific property (UPGRADINGPRODUCTCODE is a built-in MSI property).
Top Tip: MSI conditions are notoriously fiddly to get right. You can debug MSI conditions pretty efficiently by the approach described
here: How to execute conditional custom action on install and modify
only? (see bottom section - using VBScript message boxes and then
run the setup in different modes).
Minor Upgrades: Please be aware that minor upgrades are very limited - and another answer. Please review the restrictions to make sure you are aware of them and that you can release your software with them in mind. Also make sure to test repair and modify scenarios for the installer.
Advice: Often it is better to use the launch sequence of the application to perform application configuration than relying on custom actions since they have complex sequencing, conditioning and impersonation issues.
The Setup
So I have a Custom Action that is marked as Deferred and executes Before InstallFinalize. It looks like this:
<CustomAction Id="CADeferred"
BinaryKey="binaryCustomActions"
DllEntry="CADeferredMethod"
Execute="deferred"/>
<InstallExecuteSequence>
...
<Custom Action="CADeferred"
Before='InstallFinalize'>Not Installed or Upgrading</Custom>
</InstallExecuteSequence>
And I have Version 1.0 installed currently on the computer environment & fully functional. I then use the Version 2.0 MSI to do an Upgrade.
The Issue I'm Running Into
When doing the Upgrade, that Custom Action can fail and returns ActionResult.Failure. When that happens, the installer fails and says:
"Product Setup Wizard ended prematurely because of an error. Your
system has not been modified. To install this program at a later time,
run Setup Wizard again. Click the Finish button to exit the Setup
Wizard."
Once I click Finish. I checked that the product itself has been removed completely from the computer environment. Like it has been uninstalled essentially.
I was hoping it would Rollback to the Version 1.0 as it was before the Upgrade.
What I'm Trying To Accomplish
If this scenario happens, I like the installer to Rollback to Version 1.0 on the environment.
What I've Done So Far
I've researched on Google for more information on how InstallFinalize works, how Rollbacks work, etc.
From my research, having a Deferred Custom Action to run Before InstallFinalize is the way to go for a Custom Action that needs to modify state on the environment. As well as being able to use the new files on the new installer such as a DLL because it runs "inside" the InstallFinalize step. Since it's defined Before InstallFinalize I thought the Rollback of it would put the system back to the previous installed version of the product.
I've tried making it into a Immediate Custom Action to run After InstallFinalize, but that's bad. If it fails, the product still Upgraded to Version 2.0. Which is odd. Plus I know this is frown upon. So I went to Deferred Custom Action to run Before InstallFinalize.
I also read that usually Deferred Custom Actions have a Rollback Custom Action associated with it. However, due the functionality of the Deferred Custom Action, we can't necessarily fix the issue with a Rollback Custom Action. Reason is because it takes an admin to really check out the failure and manually do any changes needed for a retry of the Upgrade to work the next time. So hence we don't include an associate Rollback Custom Action.
So I'm pretty stumped at this point. Any help or direction would be very much appreciated. If I'm not being clear enough, feel free to ask for more clarification. Please and thank you.
Please read the following MSI SDK description: RemoveExistingProducts Action. Essentially the placement of the standard action RemoveExistingProducts will affect how rollback works, and in effect if it works at all. This standard action runs the uninstall of the old setup during a major upgrade - which under the hood is not really an upgrade, but an uninstall of the old product and an install of the new product - with several different "flavors" of sequencing - in other words what happens first, the uninstall or the install.
Late RemoveExistingProducts sequencing allows proper rollback (details in the SDK article linked to above). For late placement of RemoveExistingProducts to work correctly, you have to be careful that the component rules are not violated, or files will be missing after the update if you sequence the uninstall late. This is because in this scenario the new version installs as a patch. It patches the changed files and then removes whatever is obsolete. In the early uninstall scenario you "de-couple" yourself from these reference count issues - the old product is completely gone before the new one is installed - and hence you can't roll back to it (unless you manually reinstall it). In other words: early RemoveExistingProducts it is more forgiving of setup design mistakes - and hence more used in the real world.
The configuration of the major upgrade is determined by either the MajorUpgrade element or Upgrade Elements.
Some Links:
Doing Major Upgrade in Wix creates 2 entries in Add/Remove Programs
How do you detect installed product versions at each startup?
How to prevent Wix from installing an older version?
Reboot on install, Don't reboot on uninstall (not really relevant, leaving link)
Adding entries to MSI UpgradeTable to remove related products
I am trying to delete a file using a custom action scheduled between InstallInitialise and InstallFinalize standard action.
MajorUpgrade element is used to design upgrades.
However, I want the custom action to run only during uninstall and not during the Major upgrade(this includes uninstall and install).
I have used the following conditions to execute the CUstom action:
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
REMOVE AND NOT WIX_UPGRADE_DETECTED
Is there a way to uniquely detect the Major Upgrade using properties in Wix?
Phil has already answered. I'll just post what I wrote a few hours ago
before heading out. The conditions you specify look pretty good to me.
Maybe I'll do a quick review of things that are likely to cause
confusion - such as what custom actions run when?
Major Upgrades: A major upgrade is really an install of a new application version combined with the uninstall of the old version - with different uninstall scheduling possible (uninstall old and install new, or install new and uninstall old). Hence, during a major upgrade operation, 1) the uninstall sequence runs only for the old setup, and 2) the new setup runs only its install sequence. This is of crucial importance to understand what custom actions runs when and why.
Custom Actions and Major Upgrades: To put it in other words: this sequencing can cause quite a bit of confusion for custom action sequencing, since it could appear that an action runs from the new setup, when it in fact runs in the old setup's uninstall sequence. If you are sloppy with sequencing, the typical error is seeing the same action run many times during the upgrade process - potentially twice from each setup (four times in total - or perhaps even more - I haven't tested that in detail) - if you run the custom action in immediate mode.
No Retrofitting for Major Upgrades: As Phil explains, you can not add a custom action that will run during the old setup's uninstall sequence inside the new setup. That custom action would have had to be part of the original setup, or added via a minor upgrade (which upgrades the existing installation in-place, rather than uninstall and reinstall it).
Important:
UPGRADINGPRODUCTCODE is set only in a setup that is being uninstalled as part of a major upgrade. It is not set in the new
version being installed.
The condition UPGRADINGPRODUCTCODE is hence not true in the installing setup, only in the uninstalling setup.
WIX_UPGRADE_DETECTED is set only in setups that are using WiX's MajorUpgrade element that have detected that another version is
being uninstalled as part of its install.
The condition WIX_UPGRADE_DETECTED is hence true in the installing setup, but not in the uninstalling setup.
WIX_UPGRADE_DETECTED: To go into even more detail, WIX_UPGRADE_DETECTED is strictly speaking not a custom WiX feature - it is a WiX standard or convention for setting the built-in MSI property ActionProperty for the upgrade process. All MSI files supporting major upgrades have such a property, WiX just names it in a standard way. The property is set in a column in the Upgrade table, and it is a property that is set when a setup finds related products - that are lower versions (and hence to be uninstalled) - on the same box during installation.
WIX_DOWNGRADE_DETECTED: Note that in a standard WiX-compiled MSI using the MajorUpgrade element there is also WIX_DOWNGRADE_DETECTED - the property used to list products found that are of higher version than the running setup. These would block the setup in question from installing - in most cases (unless the settings are customized by the setup designer).
The action property specified in the upgrade table can be "anything", but the MajorUpgrade Element "convenience feature" does this for you in an "auto-magical" way that makes sense for most purposes - using the mentioned property names WIX_UPGRADE_DETECTED and WIX_DOWNGRADE_DETECTED. Check the Upgrade Table of your compiled MSI to see how this works in detail. Here is a screen shot:
I wrote this other answer showing how to use another property name (YOURUPGRADEPROPERTY) as "ActionProperty": wix installer update process and confirmation dialog (the linked answer is not a recommendation, demonstration only). Just a link, probably not very useful for you now that I think about it.
Some Links:
http://forum.installsite.net/index.php?showtopic=13809
NOT UPGRADINGPRODUCTCODE evaluates to true on a major upgrade for custom action
It's not obvious whether you want to do this in the older installed product (which is presumably already shipped and therefore can't be changed without an update such as a patch) or in the newer upgrade install.
I'll also assume you've looked at the RemoveFile element and it doesn't meet your requirements.
The UPGRADINGPRODUCTCODE property applies to the older product being upgraded and uninstalled. If the file belongs to that installed product and you want to remove it only at uninstall with a custom action in that older install the condition on the custom action would be:
REMOVE="ALL" and not UPGRADINGPRODUCTCODE
but as I said, that custom action would need to be already in the older installed product and there's nothing you can do in your upgrade MSI to fix that.
If you are removing the file from the upgrade then the condition during an upgrade is only:
WIX_UPGRADE_DETECTED
It might also help to say where your major upgrade is sequenced. If it's early (such as around InstallInitialize) then the upgrade is basically an uninstall of the older product followed by an install of the newer product, and that might be related to the removal of the file, if that's what you're seeing.
On the Wix's document How To: Run the Installed Application After Setup, the condition for the Publish element contains and NOT Installed aside from the property that contains whether the application should be run or not:
<Publish Dialog="ExitDialog"
Control="Finish"
Event="DoAction"
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
Why is it there? What does it do?
The custom action pointed to by the Publish element will run only when the whole condition provided evaluates to true.
NOT Installed: is true for fresh installation and major upgrade. Otherwise always false.
WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1: is true when the property is set equal to 1.
So, translating the condition into words: launch the application on fresh install and major upgrade install only when WIXUI_EXITDIALOGOPTIONALCHECKBOX is also set to 1. Otherwise do not launch. Both conditions must be satisfied for launch to happen.
Technically: Installed is essentially checking whether the product GUID of the MSI you are installing is already registered as installed on the system. If it is, then the condition NOT Installed evaluates to true.
Launching Application: Yes, this can be a bit confusing, but it does what it says in the documentation: it makes the application only launch during fresh install and not during repair, modify, uninstall, minor upgrade patch (or other installation modes).
Interestingly it should (as far as I can see) cause the application to launch during an interactive major upgrade as well (Installed is not true for the new setup being installed on top of the old one, but it is true for the uninstalling setup - a major upgrade is essentially and uninstall of the old version and a fresh install of the new version).
So NOT Installed seems to only be true in two cases: fresh install and major upgrade. The two cases where you want to auto-magically launch your application?
Since the InstallUISequence is skipped in silent installation mode, there will be no application launched after a silent install since your dialog will never be encountered (only the InstallExecuteSequence runs).
Digression, similar issue - LaunchCondition: I just commented on almost the same issue the other day in the context of LaunchConditions. If you follow the link, please be sure to read Phil's follow-up comment as well.
To use other words than above: essentially the OR'd Installed condition ensures that the LaunchCondition only applies on fresh installation (or on major upgrade for the new package being installed on top of the old one). This seems to be a nifty feature from the WiX guys - I noticed Installshield does not seem to use this concept. I haven't tested this much, but it seems like a good concept.
Alternatively, as Phil states in the linked comment above, in the context of LaunchConditions you could condition the LaunchConditions actions instead of complicating the actual LaunchConditon condition. Not sure which is better.
UPDATE:
On Conditions In General: MSI conditions can be quite confusing. Here are some resources to work them out:
Installshield Common MSI Conditions Cheat Sheet (from Installshield).
How to execute custom action only in install (not uninstall) (scroll down)
I have one further link that I tend to provide, but it has a number of subtle problems that I want to test out before sending people to the content.
It probably isn't clear from a (seemingly casual) condition such as "not Installed", but there is a set of standard Windows Installer properties, and Installed is one of them:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370905(v=vs.85).aspx
A product is "installed" if its ProductCode is registered as installed on the system. In the context of that WiX source, it means "run only when the product is not already installed".
Conditions are especially important in custom actions. If you don't put any conditions on a custom action then it will run at install time, and also whenever and install-type operation takes place, such as uninstall, repair, applying s patch. Conditions are documented here:
https://msdn.microsoft.com/en-us/library/aa368012(v=vs.85).aspx
The Not Installed condition attempts to ensure that even if WIXUI_EXITDIALOGOPTIONALCHECKBOX is set to 1 by default, the action is only published in scenarios that the exe is strongly likely to be present. Why do this? If someone selects to launch the exe when it's not present, an error message, or a missing UI, could confuse the user. In other parts of the installation process, a failed launch could abort and roll back the installer.
By then why is the condition NOT Installed? That probably sounds backwards to you. But it's not an accident. The Installed property is set at the launch of your installer, and is not updated until the next time it is launched. Even when the installer alters the state by installing or uninstalling the product, the value of Installed is left untouched.
So what are the scenarios where NOT Installed will be true on the ExitDialog?
First-time install:
Installed will start (and remain) false, so at the end NOT Installed will be true. If the installation completes successfully, your exe is probably there. If the installation is cancelled or rolls back, the installer could✱ show a different final dialog that does not offer the launch option.
Maintenance, repair, uninstallation: Installed will start as true, so at completion NOT Installed will be false. This can result in a false negative in, e.g., a repair scenario; the exe may be present but the installer will not try to launch it. But, more importantly, it prevents the attempt to launch the exe after it was just uninstalled.
Upgrades: Depending on the type of upgrade, this will be equivalent to one of the prior scenarios. Minor upgrades and small updates are a form of maintenance, whereas major upgrades act like a first-time install.
Note that this condition may not be foolproof in more complex projects. If your exe is installed only in a subset of your configurations (e.g., if it's installed only by a feature that you can choose to exclude, or by a component that depends on the version of the OS), you may want to enhance the condition or remove the launch action entirely.
✱ I say could show a different dialog because I'm uncertain what WixUI_Minimal does here. If it shows the same dialog, then the condition is insufficient to accomplish what I described here.
We have an installer which requires a reboot on install, but it is also rebooting on uninstall. Is there a way we can prevent the reboot when uninstalling?
This is what we have at the moment:
<InstallExecuteSequence>
<ScheduleReboot After="InstallFinalize"/>
</InstallExecuteSequence>
Many thanks in advance!
Restart Manager: The Restart Manager Feature of Windows (Installer) (middle page) is designed to help restart applications automatically during installation rather than requiring a reboot.
This feature should always be used to try to eliminate reboot requirements.
Only in very special circumstances should a reboot be really required.
Technical Crash Course: This is a technical tidbit and recommendation for implementing Restart Manager in your application - from Advanced Installer, makers of leading deployment tools:
https://www.advancedinstaller.com/user-guide/qa-vista-restart-manager.html
UPDATE: MSI Expert Phil Wilson on Restart Manager (for some Restart Manager reality check - please read).
Add Condition to ScheduleReboot
You need to insert a condition for your ScheduleReboot entry along the lines of what is described here: https://www.firegiant.com/wix/tutorial/events-and-actions/extra-actions/ (the linked article may show a condition that is a little too inclusive or unrestricted).
UPDATE: There are some issues to consider:
Undesired action: ScheduleReboot should never be used unless it is really necessary. For example, if you are trying to replace files that are in use MSI will handle that without a call to ScheduleReboot.
Many installation modes: Without a proper condition, the ScheduleReboot will cause a reboot prompt to show up in many installation modes: install, uninstall, upgrade, repair, self-repair, patching, etc... This is not desirable.
Silent, instant reboot: If an MSI is run in silent mode and REBOOT=ReallySuppress is not specified, a ScheduleReboot action will automatically trigger an instant reboot of the computer in question - which might be very surprising and very undesirable.
For your purpose, you can perhaps use a condition along these lines:
<InstallExecuteSequence>
<ScheduleReboot After='InstallFinalize'>NOT Installed AND NOT WIX_UPGRADE_DETECTED</ScheduleReboot>
</InstallExecuteSequence>
It all depends on whether you want to schedule a reboot during a major upgrade, or just during the original, fresh installation? There is no way to tell without more information. A more run-of-the-mill condition like NOT Installed AND NOT REMOVE~="ALL" would appear to schedule a reboot during a major upgrade, but not for a manual uninstall not triggered by a major upgrade (I will test when I get a chance - UPDATE: verified, basic testing only).
Note that the special WIX_UPGRADE_DETECTED property is a WiX-specific construct that may only be set if you use WiX's MajorUpgrade element. You can also set up major upgrades the old fashioned way in WiX and avoid the MajorUpgrade element "convenience feature" which allows easier configuration of the major upgrade with fewer options - "auto-magic". I didn't verify if WIX_UPGRADE_DETECTED is still set using this "old school" major upgrade configuration.
You can also use the ActionProperty from the Upgrade table to detect that a major upgrade is "about to happen" (see this answer for a sample). This should work even for non-WiX MSI setups - and as such should be an alternative to WIX_UPGRADE_DETECTED (I believe this property is set after FindRelatedProducts has run).
WIX_UPGRADE_DETECTED vs UPGRADINGPRODUCTCODE
The MSI package being uninstalled during a major upgrade will have the special property UPGRADINGPRODUCTCODE set (which will not be set in the MSI being installed during the upgrade). This is a built-in MSI property, and not a WiX-specific construct. In other words, during a major upgrade - which is an uninstall of an old version and an install of a new version - the MSI being uninstalled will have the property UPGRADINGPRODUCTCODE set whilst the MSI being installed will have the property WIX_UPGRADE_DETECTED set (I will verify this shortly). It will also have the ActionProperty from the Upgrade table set after the standard action FindRelatedProducts has run.
If this sounds complicated, then I am afraid it is. This is a key problem with Windows Installer (despite the technology's major corporate benefits) -
that basic, key operations - such as upgrades - are sometimes very complicated to get right. There may be some violations of the principle of least astonishment. There is good and bad in all technologies - obviously.
Special Considerations
Note that a reboot may be initiated regardless of whether the ScheduleReboot action is suppressed or not (for example if there are files that could not be replaced - or worse: a custom action forces a reboot via code - which is always wrong, a reboot should be scheduled not forced via code).
You can suppresses certain prompts for a restart of the system by using the REBOOT property (something you will have read already). More on System Reboots.
MSI Conditions
MSI conditions can be very tricky to get right. Get it wrong and your action runs unexpectedly during the wrong installation mode - or it doesn't run at all when it should. This is much easier to get wrong than what you might think - even with experience. The proof is in the pudding here, real-life testing. Here are some sample, complex conditions as an example: Wix Tools update uses old custom actions (just in case it is interesting).
There are many installation modes you should test in when you try to use complex conditions (or any condition for that matter): 1. fresh install, 2. repair, 3. modify, 4. self-repair, 5. patching, 6. uninstall, 7. major upgrade invoked uninstall, etc... There are also a few weird modes like resumed suspended installs featuring the RESUME property, and the AFTERREBOOT property relating to the ForceReboot action etc... Things one should keep in mind that are rarely tested.
Here are two "cheat-sheets" for conditioning:
Installshield condition cheat sheet.
How to add a WiX custom action that happens only on uninstall (via MSI)?
I have not had the time to go through all these conditions and test them, but the latter table looks reasonable at face value. However: I believe REMOVE can sometimes be set during installation (and during change). It is very complicated to deal with all permutations of possibilities since MSI's command line interface and property configuration is so flexible. Installed is also not set for the new MSI version being installed as part of a major upgrade, but it will be set for the MSI version being uninstalled - very confusing.
The Installshield cheat sheet I have never actively used or checked, but I find their suggestions for repair interesting to say the least - there are different entries depending on how the repair is invoked.
Please remember to also check self-repair - just delete the main application EXE and trigger self-repair by then invoking the application's advertised shortcut (if any). It has been years since I checked, but self-repair may only run actions between InstallInitialize and InstallFinalize. You don't want to schedule a reboot during a self-repair.