Understanding MSI uninstall - EXECUTEACTION = INSTALL - wix

I'm having issues with with a custom action I want to run during uninstall.
The custom action is responsible for unregistering a system level windows service.
Custom action:
<CustomAction Id='UnregisterService'
Directory='INSTALLDIR'
ExeCommand='[INSTALLUTIL] /u "/config=[INSTALLDIR]\configInstall.xml" " ...
Return='ignore'
Execute='deferred' />
This action scheduled in the InstallExecuteSequence and should be invoked on uninstall and upgrade:
<InstallExecuteSequence>
<Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
<RemoveExistingProducts After="InstallValidate" />
<Custom Action='UnregisterService' After='InstallFiles'>UPGRADEFOUND OR (Installed AND NOT UPGRADINGPRODUCTCODE)</Custom>
<Custom Action='RemAgApps' After='UnregisterService'>UPGRADEFOUND OR (Installed AND NOT UPGRADINGPRODUCTCODE)</Custom>
...
</InstallExecuteSequence>
The problem is that when I run uninstall from the ARP, uregister action does not invoked (as written in msi logs):
Skipping action: UnregisterService (condition is false)
When I dig deeper into the log (which is terrible...) I see that there is no 'uninstall' action, only install:
Property(C): EXECUTEACTION = INSTALL
Property(C): ACTION = INSTALL
Product: BLABLA -- Installation completed successfully.MSI (c) (BC:50) [14:35:37:067]: Windows Installer installed the product. Product Name: BLABLA . Product Version: 5.1.0. Product Language: 1033. Manufacturer: BLABLA Team. Installation success or error status: 0.
My questions are :
What is the flow of msi uninstall? (No couldn't find it in the web...)
Why I get the 'Install' action during uninstall?
How can I force uninstall to run my 'unregisterService' custom action?
Thanks!

Custom actions should be avoided until you fully understand Windows Installer to avoid reinventing the wheel with a more fragile solution. To remove a service during uninstall you merely need:
<ServiceControl Id="myService" Name="MyService" Stop="both" Remove="uninstall"/>
Read this good article: InstallSite: Installation Phases and In-Script Execution
Windows installer installation transactions can take many forms. Initial install, repair, maintenance install, uninstall, upgrade, patch and so on. The installer tracks the state change of features, components and products at different levels so the concept of install/uninstall is more detailed.

Related

WiX will not uninstall due to conditions in CustomAction

I have an MSI that uses two CustomActions. The first adds some stuff to the registry. It runs every time except during uninstall. The second removes a key from the registry to be run only during uninstall.
Both CustomActions work fine, only now the MSI won't uninstall.
By "it won't uninstall" I mean neither the file that is installed is deleted nor is the MSI removed from Programs and Features when uninstall is run. The only thing is does do during uninstallation is the Custom Action that removes stuff from the registry.
Note that the problem happens on a fresh Virtual Machine, so it's not like there are old versions with different GUIDs hanging around.
Also I don't think that there's a problem with the Features, as there's only one feature -- a textfile installation (it's a toy installation -- until I get this right it's not going in the real installer).
Here is the <InstallExecutiveSequence> code from both Custom Actions. The one where I put stuff into the registry, to be done every time except uninstall:
<InstallExecuteSequence>
<Custom Action="CustomAction_CreateKey"
After="InstallInitialize">
</Custom>
</InstallExecuteSequence>
And here is the same XML from where I delete from the registry, to be done only during uninstallation:
<InstallExecuteSequence>
<Custom Action="CustomAction_DeleteKey"
After="InstallInitialize">
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
</Custom>
</InstallExecuteSequence>
The uninstall logs aren't that helpful (at least, to me). There's this:
MSI (s) (BC:6C) [15:27:15:733]: Note: 1: 1725
MSI (s) (BC:6C) [15:27:15:733]: Note: 1: 2205 2: 3: Error
MSI (s) (BC:6C) [15:27:15:733]: Note: 1: 2228 2: 3: Error 4: SELECT
Message FROM Error WHERE Error = 1725
MSI (s) (BC:6C) [15:27:15:733]: Note: 1: 2205 2: 3: Error
MSI (s) (BC:6C) [15:27:15:733]: Note: 1: 2228 2: 3: Error 4: SELECT
Message FROM Error WHERE Error = 1709
MSI (s) (BC:6C) [15:27:15:733]: Product: CustomActionDeleteKeySetup --
Removal failed.
And this:
Calling custom action DeleteKey!DeleteKey.CustomActions.DeleteTheKey
Exception thrown by custom action:
System.Reflection.TargetInvocationException: Exception has been thrown
by the target of an invocation. --->
Microsoft.Deployment.WindowsInstaller.InstallerException: Cannot
access session details from a non-immediate custom action
at
Microsoft.Deployment.WindowsInstaller.Session.ValidateSessionAccess()
at Microsoft.Deployment.WindowsInstaller.Session.set_Item(String
property, String value)
at DeleteKey.CustomActions.DeleteTheKey(Session session)
--- End of inner exception stack trace ---
I'm not really sure what to look for in the log files.
To sum up: Custom Actions won't let me uninstall. I'm pulling my hair out.
EDIT
I managed to get it working, but I don't know why. It has something to do with the conditions.
The conditions were this: when uninstalling and only uninstalling, I wanted to remove the key. So -- as shown above -- here's the <InstallExecuteSequence> code:
<InstallExecuteSequence>
<Custom Action="CustomAction_DeleteKey"
After="InstallInitialize">
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
</Custom>
</InstallExecuteSequence>
And then I wanted to create the key when doing everything except installing. Before, I didn't have any conditions in the <InstallExecuteSequence> bit, but when I change it to this, it seems to work (that is, the custom actions work and it uninstalls):
<InstallExecuteSequence>
<Custom Action="CustomAction_CreateKey"
After="InstallInitialize">
(NOT installed) OR (CHANGE) OR (REPAIR)
</Custom>
</InstallExecuteSequence>
The question is: why does it work? Is it because earlier I was trying to run both Custom Actions during uninstallation?

Wix CustomAction with After='InstallFinalize' executed in upgrade to next version?

I am using the following code to start a Setup program at the end of my Installation (also with elevated permissions):
<Product ... >
...
<InstallExecuteSequence>
<Custom Action='LaunchSetupAction' After='InstallFinalize'/>
</InstallExecuteSequence>
<!-- Workaround required for Windows7, Setup.exe can not be started directly because of UAC
http://stackoverflow.com/questions/2325459/executing-a-custom-action-that-requires-elevation-after-install -->
<Property Id="WixShellExecTarget" Value='[#SetupEXE]'/>
<CustomAction Id="LaunchSetupAction" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Return="check" Impersonate="yes"/>
...
<MajorUpgrade DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
</Product>
This works well when then program is installed freshly, but when it is upgraded from a previous version with the same code, the installation reports a fatal error and fails.
In the Windows installer log I have found the following:
Action start 23:42:22: LaunchSetupAction.
...
MSI (s) (38:88) [23:42:22:342]: Invoking remote custom action. DLL: C:\WINDOWS\Installer\MSI679.tmp, Entrypoint: WixShellExec
...
WixShellExec: WixShellExecTarget is C:\Program Files\Me\MySetup.exe
...
WixShellExec: Error 0x80070002: ShellExec failed with return code 2
...
WixShellExec: Error 0x80070002: failed to launch target
...
Action ended 23:42:22: LaunchSetupAction. Return value 3.
Action ended 23:42:22: INSTALL. Return value 3.
Interesting enough these error messages (file not found?) is also there when I comment out the CustomAction in the new version of the installer.
Why is this CustomAcount executed from the previous version to be uninstalled?
Is there any way I can stop it from being run? After a certain point of the upgrade, the MySetup.exe is just not there anymore and will always cause a fatal error ...
That custom action has no condition on it, so it will be called on all types of installer operations, such as uninstall, add/remove features etc. Your upgrade is an install of the new product and an uninstall of the old product.
You need this kind of thing on your custom action:
Wix: Run custom action based on condition
so a condition of 'Not Installed' causes the CA to run only if the product is not already installed.
You can't really fix this because the uninstall for that product is embedded in the system. You'd need to fix that older version of the product by rebuilding the exact same product with the custom action condition fixed and then fix it with:
msiexec /i [path to new MSI] REINSTALL=ALL REINSTALLMODE=vomus
If you're very familiar with MSI and Orca, you may be able to locate the cached MSI file in C:\windows\installer, open it with Orca, go the InstallExecuteSequence and give that custom action a condition of 0, then save it. That basically corrects the uninstall sequence so that your upgrade will work. Caveat Emptor.
It also appears that a plain uninstall would give you same error - did you every try to do an uninstall test?

Is there an updated truth table for WiX custom action conditions?

I am trying to get some custom actions working properly on my install.
This is the table I am using for my logic in Wix (provided by ahmd0)
The problem is that it just doesn't seem to be working. Here are my conditions currently:
<Custom Action='RemoveService' After='InstallInitialize'>Installed</Custom>
<Custom Action='WaitForFileLocks' After='InstallInitialize'>Installed</Custom>
<Custom Action='InstallService' Before='InstallFinalize'>NOT REMOVE ~= "ALL" OR UPGRADINGPRODUCTCODE</Custom>
<Custom Action='MergeConfigFiles' Before='InstallFinalize'>NOT REMOVE ~= "ALL" OR UPGRADINGPRODUCTCODE</Custom>
The behavior I expect from this:
RemoveService and WaitForFileLocks should be run on uninstalls and upgrades.
InstallService and MergeConfigFiles should be run on installs and upgrades.
The behavior I am seeing:
RemoveService and WaitForFileLocks are running on uninstall, but NOT upgrades.
InstallService and MergeConfigFiles is being run on install, but NOT upgrades.
Is the table I am using wrong? Is my logic correct? Could my issue be Windows' recognition of what an "upgrade" is? I checked in Add/Remove programs after I increased all 3 version numbers for my install and the new version is properly updating there.

How can I perform a custom action in WiX that only executes on install or uninstall?

I have two custom actions, one of which I'd like to execute when my product is installed and the other when it is uninstalled.
My custom action is currently called from a merge module after the "InstallFinalize", but this happens for both install and uninstall. I've tried adding the "NOT INSTALLED AND NOT UPGRADINGPRODUCTCODE" condition, but that gave me an error:
Error 2762. Cannot write script record. Transaction not started.
I've also tried attaching to other actions (for example, UnpublishComponents), but I can't find any that are unique to install or uninstall.
How can I fix this problem?
Try next
1. Only for Installation:
<InstallExecuteSequence>
<Custom Action="SomeAction" After="InstallFinalize">NOT Installed AND NOT REMOVE</Custom>
</InstallExecuteSequence>
2. For Uninstall try to use: Rob's answer
UPGRADINGPRODUCTCODE property is set only during RemoveExistingProducts CA.
The variable “INSTALLED” should be using is “Installed”. Find more information regarding the Install and uninstall conditions in the Stack Overflow answer How to add a WiX custom action that happens only on uninstall (via MSI)?.

Wix - Run custom action when modifying existing install

I'm trying to run a custom action on first install and any subsequent modification(adding/removing features of the installed product).
Which condition should I check?
I'm using the following but it doesn't work.
<InstallExecuteSequence>
<Custom Action='SetParams' After='InstallFinalize'>NOT Installed OR WixUI_InstallMode = "Change"</Custom>
</InstallExecuteSequence>
Thanks
You can try this condition:
REMOVE <> "ALL"
It's true for a first time install and any maintenance operation except uninstall.