"Installed" condition is always true when installing or uninstalling in WiX - wix

I have a WiX installer which does some work, and at the end, launch RSYNC installer (it's an EXE file, no problem to have both working at same time).
But when uninstalling, I want to remove RSYNC too.
<CustomAction Id="InstallRSyncDaemon" FileKey="cwRsyncServer_4.0.5_Installer.exe" ExeCommand="/q" Execute="deferred" Return="ignore" Impersonate="no" />
<CustomAction Id="UninstallRSyncDaemon" FileKey="rsync_uninstall.bat" ExeCommand="[INSTALLDIR]" Execute="deferred" Return="check" Impersonate="no" />
<CustomAction Id="EditConf" FileKey="rsync.bat" ExeCommand="[INSTALLDIR]" Execute="deferred" Return="ignore" Impersonate="no"/>
<InstallExecuteSequence>
<Custom Action='InstallRSyncDaemon' Before='InstallFinalize'>(NOT remove="ALL")</Custom>
<Custom Action='EditConf' After='InstallRSyncDaemon'>(NOT remove="ALL")</Custom>
<Custom Action='UninstallRSyncDaemon' Before='RemoveFiles'>remove="ALL"</Custom>
</InstallExecuteSequence>
My problem is that during uninstalling, the Custom Action 'UninstallRSyncDaemon' is skipped:
MSI (s) (58:78) [17:37:40:475]: Skipping action: UninstallRSyncDaemon (condition is false)
I have tried with "installed" and other conditions, with the same result.
At the beginnning of the log file, I have:
MSI (c) (9C:80) [17:37:36:772]: PROPERTY CHANGE: Adding ACTION property. Its value is 'INSTALL'.
MSI (c) (9C:80) [17:37:36:772]: Doing action: INSTALL
Action 17:37:36: INSTALL.
Action start 17:37:36: INSTALL.
MSI (c) (9C:80) [17:37:36:772]: UI Sequence table 'InstallUISequence' is present and populated.
MSI (c) (9C:80) [17:37:36:772]: Running UISequence
MSI (c) (9C:80) [17:37:36:772]: PROPERTY CHANGE: Adding EXECUTEACTION property. Its value is 'INSTALL'.
If I try to change to the condition to launch it during installation, it is working, so for me it is just the statement of the condition.
But I do not understand why, this is the condition always used in a tutorial or in an answer on Stack Overflow.

I think the remove should be in upper case. Try this.
REMOVE="ALL"
But it will run in modify and Upgrade also. Check more about this condition here.

Related

WiX Toolset Extension: How to make an order of a Custom Action configurable?

I am in progress with a custom WiX Toolset Extension and would like to know, if it is possible to make a custom action's order configurable?
For example, I have two actions:
CreateFolder Custom Action:
CustomAction Id="CreateFolder" BinaryKey="My.Ext.CA" DllEntry="CreateFolder" Execute="deferred"
ExecuteSql Custom Action:
CustomAction Id="ExecuteSql" BinaryKey="My.Ext.CA" DllEntry="ExecuteSql" Execute="deferred"
They are placed in the InstallExecuteSequence in the next order:
<InstallExecuteSequence>
<Custom Action="CreateFolder" After="InstallValidate">
NOT Installed
</Custom>
<Custom Action="ExecuteSql" Before="InstallFinalize">
NOT Installed
</Custom>
</InstallExecuteSequence>
It works fine for executing CreateFolder CA first, and then ExecuteSql.
But, in some cases it is required for WixExtension user to run ExecuteSql first, and CreateFolder comes next.
Can I somehow specify a CA order to be executed within InstallExecuteSequence and make it configurable?

Wix CloseApplication error

I wrote an installer with wix 3.9 and it should close my App, if it is opened, during installation.
Following many examples, I wrote this code:
<util:CloseApplication
Id="CloseApp"
CloseMessage="yes"
Description="Close [ProductName] to continue installation"
RebootPrompt="yes" Target="[ProductName].exe"/>
<InstallExecuteSequence>
<Custom Action="DIRCA_TARGETDIR"
Before="CostInitialize"><![CDATA[TARGETDIR = ""]]></Custom>
<Custom Action="WixCloseApplications"
Before="InstallValidate"></Custom>
</InstallExecuteSequence>
But when I run my .msi, it fails and log says:
Action 15:54:34: WixCloseApplicationsDeferred.
Action start 15:54:34: WixCloseApplicationsDeferred.
MSI (s) (A0!94) [15:54:34:804]: Note: 1: 2762
DEBUG: Error 2762: Unable to schedule operation. The action must be scheduled between InstallInitialize and InstallFinalize.
What's wrong?

Wix - Running a deferred action after InstallFinalize

Reading the Wix help I see that "Deferred execution custom actions must come after InstallInitialize and come before InstallFinalize in the action sequence."
However I have to perform a database upgrade on a remote box which needs to be run with the user credentials so I have created an immediate action and set it to run after installFinalize. Subsequently, I need to run another custom action to start a windows service which reads values from the database, this requires elevated (system) permissions, so needs to be a deferred custom action. Which as the Wix help kindly explains to me that I cannot do.
Any help, tips or Wix tricks appreciated please
<CustomAction Id="LaunchServerUpgrade" FileKey="Config.exe" ExeCommand="/upgradeServer"
Return="ignore" Execute="deferred" Impersonate="no"/>
<CustomAction Id="LaunchServerDatabaseUpgrade" FileKey="Config.exe" ExeCommand=" /databaseupgrade"
Return="ignore" Execute="immediate"/>
<CustomAction Id="LaunchServerStartServices" FileKey="Config.exe" ExeCommand=" /startservices"
Return="ignore" Execute="deferred" Impersonate="no"/>
<InstallExecuteSequence>
<Custom Action="LaunchServerUpgrade" Before='InstallFinalize'>
<![CDATA[(SERVERCONFIGUPGRADE) AND NOT REMOVE)]]>
</Custom>
<Custom Action="LaunchServerDatabaseUpgrade" After='InstallFinalize'>
<![CDATA[(SERVERCONFIGUPGRADE) AND NOT REMOVE)]]>
</Custom>
<Custom Action="LaunchServerStartServices" After='InstallFiles'>
<![CDATA[(SERVERCONFIGUPGRADE) AND NOT REMOVE)]]>
</Custom>
</InstallExecuteSequence>

WiX CustomAction fires in UI but not Execute Sequence

We need our MSI to store the password in the registry, so users can use our installer to change connection strings, etc.
We found MsiExt for its cryptography DLL and are trying to configure the custom actions.
Our users will need to be able to install both through the UI dialogs and silently -- so we need to able to execute in both sequences.
Here is a sample of our Product.wxs
<Property Id="DB_PASSWORD" Secure="yes"/>
<Property Id="P.DB_PASSWORD">
<RegistrySearch Id="S.DB_PASSWORD" Root="HKLM" Key="SOFTWARE\$(var.Manufacturer)\$(var.ProductName)" Name="DB_PASSWORD" Type="raw" Win64="$(var.Win64)"/>
</Property>
<Component Id="c.RegistryEntries" Guid="XXXXX-XXXXX-XXXXX-XXXXX" Directory="INSTALLDIR">
<RegistryKey Root="HKLM" Key="SOFTWARE\$(var.Manufacturer)\$(var.ProductName)" Action="createAndRemoveOnUninstall">
<RegistryValue Id="R.DB_PASSWORD" Name="DB_PASSWORD" Value="[ENCRYPTED_DBPASSWORD]" Type="string" />
</RegistryKey>
</Component>
<!--For encrypting the database password on the way to the registry-->
<Binary Id="Cryptography" SourceFile="..\..\lib\msiext-1.4\CustomActions\Cryptography.dll"/>
<!--This property will receive the encrypted DB_PASSWORD that the user enters and will be encrypted-->
<Property Id="CRYPTPROTECT_DATA" Hidden="yes" />
<Property Id="CRYPTPROTECT_FLAGS" Value="CRYPTPROTECT_LOCAL_MACHINE|CRYPTPROTECT_UI_FORBIDDEN" />
<CustomAction Id="EncryptPassword" BinaryKey="Cryptography" DllEntry="CryptProtectDataHex" Execute="immediate" />
<CustomAction Id="SetDBUSERsPASSWORDForEncryption" Property="CRYPTPROTECT_DATA" Value="[DB_PASSWORD]" />
<Property Id="ENCRYPTED_DBPASSWORD" Hidden="yes" />
<SetProperty Id="ENCRYPTED_DBPASSWORD" Value="[CRYPTPROTECT_RESULT]" Sequence="execute" After="SetDBUSERsPASSWORDForEncryption" />
<!--This is for decrypting the registry value-->
<Property Id="CRYPTUNPROTECT_DATA" Hidden="yes" />
<Property Id="CRYPTUNPROTECT_FLAGS" Value="CRYPTPROTECT_LOCAL_MACHINE|CRYPTPROTECT_UI_FORBIDDEN" />
<SetProperty Id="CRYPTUNPROTECT_DATA" Value="[P.DB_PASSWORD]" Before="DecryptPassword" >NOT(DB_PASSWORD)</SetProperty>
<CustomAction Id="DecryptPassword" BinaryKey="Cryptography" DllEntry="CryptUnprotectDataHex" Execute="firstSequence" />
<CustomAction Id="SetDBUSERsDecryptedPASSWORD" Property="DB_PASSWORD" Value="[CRYPTUNPROTECT_RESULT]"/>
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<InstallUISequence>
<Custom Action="DecryptPassword" After="CostFinalize"><![CDATA[NOT(DB_PASSWORD)]]></Custom>
<Custom Action="SetDBUSERsDecryptedPASSWORD" After="DecryptPassword" ><![CDATA[NOT(DB_PASSWORD)]]></Custom>
</InstallUISequence>
<InstallExecuteSequence>
<Custom Action="SchedXmlConfig" After="InstallFiles"><![CDATA[(NOT REMOVE~="All")]]></Custom>
<Custom Action="SetDBUSERsPASSWORDForEncryption" Before="InstallInitialize" />
<Custom Action="EncryptPassword" After="SetDBUSERsPASSWORDForEncryption" />
<Custom Action="DecryptPassword" Before="InstallFiles"><![CDATA[CRYPTUNPROTECT_RESULT]]></Custom>
<Custom Action="SetDBUSERsDecryptedPASSWORD" After="DecryptPassword" ><![CDATA[CRYPTUNPROTECT_RESULT]]></Custom>
</InstallExecuteSequence>
The install log shows that the DecryptPassword is firing during the UISequence. The decryption custom action fires, then the DecryptPassword works.
Action ended 17:52:43: CostFinalize. Return value 1.
MSI (c) (CC:A8) [17:52:43:936]: Doing action: SetCRYPTUNPROTECT_DATA
Action 17:52:43: SetCRYPTUNPROTECT_DATA.
Action start 17:52:43: SetCRYPTUNPROTECT_DATA.
MSI (c) (CC:A8) [17:52:43:937]: PROPERTY CHANGE: Adding CRYPTUNPROTECT_DATA property. Its value is '**********'.
Action ended 17:52:43: SetCRYPTUNPROTECT_DATA. Return value 1.
MSI (c) (CC:A8) [17:52:43:937]: Doing action: DecryptPassword
Action 17:52:43: DecryptPassword.
Action start 17:52:43: DecryptPassword.
MSI (c) (CC:7C) [17:52:49:129]: Invoking remote custom action. DLL: C:\Users\kujotx\AppData\Local\Temp\MSI9904.tmp, Entrypoint: CryptUnprotectDataHex
MSI (c) (CC:54) [17:52:49:130]: Cloaking enabled.
MSI (c) (CC:54) [17:52:49:130]: Attempting to enable all disabled privileges before calling Install on Server
MSI (c) (CC:54) [17:52:49:130]: Connected to service for CA interface.
CryptUnprotectDataHex: MSI Extensions 1.4.1114.0
MSI (c) (CC!94) [17:52:49:236]: PROPERTY CHANGE: Adding CRYPTUNPROTECT_RESULT property. Its value is 'password'.
Action ended 17:52:49: DecryptPassword. Return value 1.
MSI (c) (CC:A8) [17:52:49:238]: Doing action: SetDBUSERsDecryptedPASSWORD
Action 17:52:49: SetDBUSERsDecryptedPASSWORD.
Action start 17:52:49: SetDBUSERsDecryptedPASSWORD.
MSI (c) (CC:A8) [17:52:49:239]: PROPERTY CHANGE: Adding DB_PASSWORD property. Its value is '**********'.
Action ended 17:52:49: SetDBUSERsDecryptedPASSWORD. Return value 1.
My problem is that SetCRYPTUNPROTECT_DATA is not executing during ExecuteSequence, so DecryptPassword fails:
Action ended 17:53:47: AppSearch. Return value 1.
MSI (s) (28:1C) [17:53:47:206]: Doing action: DecryptPassword
Action 17:53:47: DecryptPassword.
Action start 17:53:47: DecryptPassword.
MSI (s) (28:98) [17:53:47:217]: Invoking remote custom action. DLL: C:\Windows\Installer\MSI9020.tmp, Entrypoint: CryptUnprotectDataHex
CryptUnprotectDataHex: MSI Extensions 1.4.1114.0
CryptUnprotectDataHex: [CryptUnprotectDataHex] std::exception: 0x80070057 - Error in CryptUnprotectData: The parameter is incorrect.
MSI (s) (28!DC) [17:53:47:237]: PROPERTY CHANGE: Adding CA_ERROR property. Its value is '0x80070057 - Error in CryptUnprotectData: The parameter is incorrect.'.
CustomAction DecryptPassword returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 17:53:47: DecryptPassword. Return value 3.
Action ended 17:53:47: INSTALL. Return value 3.
Can you point out how to schedule our custom actions to get this to decrypt properly?
Your problem is likely due to one of the following:
The <SetProperty> element that sets the CRYPTUNPROTECT_DATA property is being conditionally run based on the value of DB_PASSWORD not being set, but we can't see from the logs that this property is indeed not set. The property action won't run if this evaluates to false.
The default setting for the Sequence attribute on the <SetProperty> element is not working correctly. Try setting the Sequence attribute to first, which will schedule it to be run in the first of either InstallUISequence or InstallExecuteSequence (will be first in silent mode). If that doesn't work, try setting it to both explicitly.
Try changing the Before attribute on the custom action for DecryptPassword in the InstallExecuteSequence to After="InstallInitialize", which is much earlier on in the install sequence than InstallFiles. This will get you behavior that is similar to running with the UI Sequence, which computes and modifies your properties and runs your actions prior to anything actually being installed.
See this page for suggested sequencing (and see relative ordering of events)

Cannot run default browser from WIX installation

From tutorial:
<Property Id="BROWSER">
<RegistrySearch Id='DefaultBrowser' Type='raw' Root='HKCR' Key='http\shell\open\command' />
</Property>
<CustomAction Id='LaunchBrowser' Property='BROWSER' ExeCommand='www.something.com' Return='asyncNoWait' />
<InstallExecuteSequence>
...
<Custom Action='LaunchBrowser' After='InstallFinalize'>NOT Installed</Custom>
</InstallExecuteSequence>
As I can see from installation traces, property BROWSER is calculated correctly:
Property(S): BROWSER = "C:\Program Files (x86)\Internet
Explorer\iexplore.exe" -nohome
But browser is not open after installation.
MSI (s) (88:90) [18:38:30:331]: Doing action: LaunchBrowser MSI (s)
(88:90) [18:38:30:331]: Note: 1: 2205 2: 3: ActionText Action start
18:38:30: LaunchBrowser. Action ended 18:38:30: INSTALL. Return value
1. Action ended 18:38:30: LaunchBrowser. Return value 1631.
...
MSI (c) (64:6C) [18:38:30:409]: Product: WebPrintingService -- Installation completed successfully.
What could be wrong?
Windows 7.
UAC - default.
UPDATE:
As a workaround it is possible to use following code(but I am not sure that it is a good workaround):
<Property Id="BROWSER">
<RegistrySearch Id='DefaultBrowser' Type='raw' Root='HKCR' Key='http\shell\open\command' />
</Property>
<CustomAction Id="LaunchBrowser" Directory="INSTALLDIR" Impersonate="no" Execute="deferred" ExeCommand='[BROWSER] "test.html"' Return="check"/>
<InstallExecuteSequence>
<Custom Action='LaunchBrowser' Before='InstallFinalize'>NOT Installed</Custom>
</InstallExecuteSequence>
I have not made an installer that can run the default browser after installtion but I have made an installer with WiX that launches the installed application. As far as I know, the ExeCommand property must contain the file path to an executable file. It can be either the path on your computer directly or a string property you defined containing the file path. Maybe you can tell the program wich file it should open, wich would be in your case a website.
I hope this helps.