Accessing variable in Wix CustomAction ExecCommand - wix

I have a custom action in my WiX script to copy installation log:
<CustomAction Id="CopyLogFile" Execute="immediate"
ExeCommand="cmd /c copy [MsiLogFileLocation] "\"[APPLICATIONFOLDER]Install.log\"""
Directory="TARGETDIR"
Impersonate="no"
Return="asyncNoWait" />
<InstallExecuteSequence>
<Custom Action="CopyLogFile" OnExit="success" />
</InstallExecuteSequence>
The problem is the APPLICATIONFOLDER environment variable. No matter how I try to use it it does not work. I tried single &quot, double &quot, no &quot, etc. Nothing helps.
If I hard-code the destination like this:
ExeCommand="cmd /c copy [MsiLogFileLocation] c:\temp\Install.log"
it works fine.
However, I need to copy the install log to some known location on the user's machine.
I looked at WiX CustomAction ExeCommand failing?, and Not able to send Wix SourceDir path with spaces to custom action ExeCommand but it does not help with this issue.

According to Windows Installer Formatted reference your commandline should be:
cmd /c copy [MsiLogFileLocation] "\"[%APPLICATIONFOLDER]Install.log\""
^
You are missing the % prefix for environment variables.

Related

WiX Toolset - issues running cmd in Custom Action

I'm trying to add a custom action that will delete files from the installation folder using the following code:
<CustomAction Id="InstallService" Return="check" Impersonate="no" Execute="deferred" Directory="INSTALLFOLDER" ExeCommand='cmd.exe /C del /s /q "[INSTALLFOLDER]"'/>
<InstallExecuteSequence>
<Custom Action="InstallService" Before ="InstallFiles">NOT Installed AND NOT REMOVE</Custom>
</InstallExecuteSequence>
This works on some computers but fails on others showing a message
A program required for install to complete could not be run.
And in the installation logs I see
Error 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor
Any idea why this might happen or how to make it work?

WIX CustomAction terminates with error 1721 or 1722

I'm trying to create a MSI installer for my application which is a customized elasticsearch. I need to run elasticsearch-service.bat install command from cmd in the middle of installation. But whatever I do it will not execute successfully.
<CustomAction Id="InstallService" Directory="elasticsearch" Execute="deferred" Impersonate="no" ExeCommand='[SystemFolder] cmd.exe /c "bin\elasticsearch-service.bat install"' Return="check" />
<InstallExecuteSequence>
<Custom Action="InstallService" After="InstallFiles" />
</InstallExecuteSequence>
1721 and 1722 errors are vague and do not contain any additional information. What is the reason for these error? I was suspicious that these errors are due to lack of admin privileges. But I add InstallPrivileges=elevated and InstallScope=perMachine to package element and still getting the same error.
I agree with Stein, that you should use the built-in facilities of MSI/WiX to install the service, namely the <ServiceInstall> and <ServiceConfig> elements.
That being said, these are the errors of your current solution:
Space between [SystemFolder] and cmd.exe.
Executable path is not quoted.
Relative path to .bat file. Very fragile.
Possible solution:
<CustomAction Id="InstallService" Directory="elasticsearch" Execute="deferred" Impersonate="no" ExeCommand='"[elasticsearch]bin\elasticsearch-service.bat" install' Return="check" />
You can call a batch file directly, without passing it to cmd.exe.

How to execute the custom action in silent mode in wix?

I am trying to execute the custom action at the time of uninstall the installer in wix.It is working perfectly but it is showing the splash screen of cmd prompt at the time of custom action.Latter I tried with CAQuietExec but it is unable to uininstall the installer and giving error.
(CAQuietExec: Error 0x80070057: failed to get command line data).
The command that I am using is :
<Fragment>
<Property Id="ModifyOutlookRegInitSign_14" Value=""[SystemFolder]reg.exe" ADD "HKCU\SOFTWARE\Microsoft\Office\14.0\Outlook\Security" /v InitSign /t REG_DWORD /d 0 /f"/>
<CustomAction Id="ModifyOutlookRegInitSign_14" BinaryKey="WixCA" DllEntry="CAQuietExec"
Execute="deferred" Return="check" />
<InstallExecuteSequence>
<Custom Action="ModifyOutlookRegInitSign_14" Before="InstallFinalize"></Custom>
</InstallExecuteSequence>
</Fragment>
If it is an immediate custom action, the name of the property containing the command line as value must have an Id="QtExecCmdLine". For other types of custom actions read Quiet Execution Custom Action.
It seems to me that you are trying to update HKCU during the uninstall. This is probably because Windows Installer doesn't natively support the ability to do so.
But your proposed solution is lacking in several way. Mainly that it doesn't support rollback and doesn't support cleaning up other user profiles.
Did this registry entry had to be implemented in HKCU? Could it be implemented in HKLM?
I've created a custom action to kill a process silently like this:
<!-- WixQuietExecCmdLine specify the cmd to be executed -->
<Property Id="WixQuietExecCmdLine" Value='"[WindowsFolder]System32\TaskKill.exe" /F /T /IM MyApp.exe'/>
<!-- From WiX v3.10, use WixQuietExec -->
<CustomAction Id="MyAppTaskKill" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore"/>
<!-- trigger the custom action -->
<InstallExecuteSequence>
<Custom Action='MyAppTaskKill' Before='InstallValidate'></Custom>
</InstallExecuteSequence>
You have more info about the possible configuration combinations here:
http://wixtoolset.org/documentation/manual/v3/customactions/qtexec.html
Wrap your custom action around a Property with Id set to WixQuietExecCmd.
<Property Id="WixQuietExecCmdLine" Value="command line to run"/>
WiX Property Element
WiX Quiet Execution of Custom Action

Is it possible to have a batch file as a binary element type in Wix?

Here's my wix
<Binary Id="B.RenameFiles" SourceFile="RenameFiles.bat"/>
<CustomAction Id="CA.RenameFiles" BinaryKey="B.RenameFiles"
ExeCommand="RenameFiles.bat" Execute="immediate" Return='ignore'/>
<InstallExecuteSequence>
<Custom Action="CA.RenameFiles" Before="InstallValidate"></Custom>
</InstallExecuteSequence>
This doesn't work and spits out an error in the msi log "A program required for this install to complete could not be run". I'm not really sure if this is possible or if binary is only for use with exe's and dll's etc.
The way i'm doing it at the moment is to install the bat file and then run it from there but it would be neater if I could use it as a binary instead and not install it on the local machine.
Thanks
Neil
BAT files cannot be launched directly by Windows Installer custom actions. You need a custom action which uses ShellExecute to launch your BAT.
So you can't use a BAT as a Binary custom action.
Agree with Cosmin, you cannot execute BAT from binary, however you can launch it (almost) at any time during installation with help of "CMD.exe /C " custom action, and even have it run hidden (without cmd.exe window), i.e. for deffered CA one can use:
<CustomAction Id="Set_CA_HiddenBAT" Property="CA_HiddenBAT" Value=""cmd.exe" /c "[DirectoryWhereBatFileInstalled]Your.bat"" />
<CustomAction Id="CA_HiddenBAT" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="yes" />
Or if you want it visible:
<CustomAction Id="CA_LaunchBAT" Directory="DirectoryWhereToExecute" ExeCommand="CMD.exe /c "[DirectoryWhereBatFileInstalled]Your.bat"" Return="ignore" />
Note: Remember to run CA_HiddenBAT / CA_LaunchBAT after InstallFiles action and have added WixUtilExtension to your .wixproj:
<LinkerAdditionalOptions>-ext WixUtilExtension</LinkerAdditionalOptions>
<CompilerAdditionalOptions>-ext WixUtilExtension</CompilerAdditionalOptions>
There's also a way to launch BAT before InstallFile action, but this is tricky, let me know if you need this.

CAQuietExec Command string must begin with quoted application name

Ok I believe I'm following the online example in Wix3.5 for doing quiet commands yet I cannot seem to get my command to be executed quoted.
<Component Id="MapObjectsRuntime' Guid='*'>
<File Id = 'Mo23rtEXE' Name='Mo23rt.exe' Source='....' KeyPath="yes"/>
<Component>
<Property Id = "QtExecCmdLine" Value="Mo23rt.exe" />
// I've tried single & double quotes, and double double quotes around Mo23.
<CustomAction Id = "InstallMapObjects" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="immediate" Return="check" />
<InstallExecuteSequence>
<Custom Action="InstallMapObjects" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
I do get a warning building the wix project:
The file Mo23rtEXE is not a Font, and its version is not a companion file reference.
I also need to assign command line parameters to the mo23rt.exe command but I'm first just trying to get this to work.
Lots of folks appear to be struggling with this too, as revealed by Google.
Forgot to add that running setup.exe /l*v install.log had:
MSI Doing action: InstallMapObjects
.
.
Property Change: Deleting QtExeCmdLine property. Its current value is 'Mo23rt.exe'.
CAQuitExec: Command string must begin with quoted application name.
CAQuietExec: Error 0x80070057 invalid command line property value
You schedule your custom action as immediate, but you try to run a file which should be installed by your installer. Here comes the conflict: immediate CA run BEFORE the files are installed, 'cause this happens in deferred sequence.
I would recommend you to get acquainted with Installation Phases and In-Script Execution Options for Custom Actions in Windows Installer article first.
I had tried ""mo23rt.exe"" and "'mo23rt.exe'", shame on me for not trying '"mo23rt.exe"'. Something else is still wrong but it might be what's mentioned above, or it might be I'm trying to run something that is trying to put up a status bar dialog and is not really that quiet.
I changed it to a regular custom action vice CAQuiet.
<CustomAction Id="InstallMapObjects" FileKey="Mo23rtEXE" ExeCommand="/ACDJKLM" Execute="commit"/>
followed by
<InstallExecuteSequence>
<Custom Action="InstallMapObjects" Before="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>