Is it possible to have a batch file as a binary element type in Wix? - 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.

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.

Accessing variable in Wix CustomAction ExecCommand

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.

Running an EXE with parameters after installation of the files using WIX

I have this installer through which I'm installing Mosquitto as a re-requisite for my system. But after installation I need to run the EXE passing two parameters. The command to run would be "mosquitto -v -c mosquitto.conf". I tried to do this using the following command but nothing happens.
<Property Id="WixShellExecTarget" Value="[mosquitto.exe] -v -c mosquitto.conf" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<InstallExecuteSequence>
<Custom Action="RunMosquitto" Before="InstallFinalize" />
</InstallExecuteSequence>
what is the right way to do this? Also I need to stop this EXE during uninstallation. How can I do that as well? Any help would be much appreciated. Thanks.
No, according to this WiX mailing list archive.
Bob Arnson, one of the WiX developers, said the following:
WixShellExecTarget must be only the path of the executable/document.
There's no support to add arguments. For that, use a "normal" exe custom
action instead of WixShellExec.

WiX Toolset - CustomAction for uninstall running after RemoveFiles

On install I add a configuration key to a DB using a command line tool. On uninstall, I'm now trying to remove that configuration key. On an upgrade, I need to remove then add the configuration key back.
Here's my CustomAction "redacted" code:
<CustomAction Id="Unset_AppName_Version_Cmd"
Property="Unset_AppName_Version"
Execute="immediate"
Value=""[SystemFolder]cmd.exe" /C ""[SOMEDIR]SomeClTool" "uninstall:appname""" />
<CustomAction Id="Unset_AppName_Version"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="immediate"
Return="check"
Impersonate="yes" />
Note: I've tried several values for execute, including oncePerProcess, firstSequence, and immediate.
Here's my InstallExecuteSequence "redacted" code:
<Custom Action="Unset_AppName_Version_Cmd" Sequence="1215">
(!AppName = 3 AND (&AppName = 3 OR &AppName = 2))
</Custom>
<Custom Action="Unset_AppName_Version" Sequence="1216">
(!AppName = 3 AND (&AppName = 3 OR &AppName = 2))
</Custom>
Note: Again, I tried to move around the sequence used. In the above example before InstallValidate, but also before RemoveFiles, RemoveODBC, etc.
Nothing has worked for me. In all instances, the
Executing op: ActionStart(Name=Unset_AppName_Version,,)
line is being run after RemoveFiles, so my custom action fails with:
CAQuietExec: The system cannot find the path specified.
CAQuietExec: Error 0x80070001: Command line returned an error.
CAQuietExec: Error 0x80070001: CAQuietExec Failed
After this, my installation gets rolled back.
Also, is this condition correct for run on uninstall or reinstall?
(!AppName = 3 AND (&AppName = 3 OR &AppName = 2))
Thanks
Update 7/31/2015
While I still do not have a working solution, I have made enough changes that it makes sense to post my current code.
Here's my updated CustomAction "redacted" code:
<CustomAction Id="Unset_AppName_Version_Cmd"
Property="QtExecCmdLine"
Value=""[SystemFolder]cmd.exe" /C ""[SOMEDIR]SomeClTool" "uninstall:appname"""
Execute="immediate" />
<CustomAction Id="Unset_AppName_Version"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="immediate"
Return="ignore" />
Note: These changes were made based on Kiran's much appreciated suggestions and to mimic some taskkill commands that are working for me.
Example of working code:
<CustomAction Id="TaskKill_erl_exe_Cmd"
Property="QtExecCmdLine"
Value='"[SystemFolder]taskkill.exe" /F /IM erl.exe /T'
Execute="immediate" />
<CustomAction Id="TaskKill_erl_exe"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="immediate"
Return="ignore"/>
Thanks
Couple of things here.
-You are trying to execute the custom action in immediate mode using the Wix provided inbuilt Quiet Execution Custom Action.
http://wixtoolset.org/documentation/manual/v3/customactions/qtexec.html
If you want to make use of CAQuietExec in immediate mode, the documentation clearly suggests that you have to set the WixQuietExecCmdLine property.
I dont see that being done in your case.
In your case, i see that you are setting a property named Unset_AppName_Version in the immediate mode. This just wont work.
-If you are trying to use CAQuietExec in deferred mode, your authoring of the custom actions in the pasted code snippet will work, as that would lead to populating the value of the inbuilt special property "CustomActionData"
-If the command line tool that you are trying to launch is installed by the msi package, then the custom action with Id="Unset_AppName_Version" has to be sequenced after "InstallFiles" standard action for the case of Install/Upgrade/Re-install.
For the case of uninstall, i am assuming you will have a seperate custom action which invokes this command line tool with a different set of parameters and it should be sequenced before "RemoveFiles" standard action.
-Finally, yes your condition is correct and will invoke the action on re-install or uninstall of the feature.
-Also when you run your msi package, if you want to confirm if the command line tool was indeed launched, you can have a utility named "ProcessMonitor" running. ProcessMonitor is from the Sysinternals suite. Keep the tool running by setting the appropriate filters.
If your tool is ever launched, ProcessMonitor will indicate the same to you.
Hope this helps.
This ended up working for me:
<CustomAction Id="Unset_AppName_Version_Cmd"
Property="QtExecCmdLine"
Value=""[SystemFolder]cmd.exe" /C ""[SOMEDIR]SomeClTool" "uninstall:appname"""
Execute="immediate" />
<CustomAction Id="Unset_AppName_Version"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="immediate"
Return="ignore" />
And in the InstallExecuteSequence:
<Custom Action="Unset_AppName_Version_Cmd" Sequence="1215">
(!AppName = 3 AND (&AppName = 3 OR &AppName = 2))
</Custom>
<Custom Action="Unset_AppName_Version" Sequence="1216">
(!AppName = 3 AND (&AppName = 3 OR &AppName = 2))
</Custom>
The issue seems to be that something got messed up in my VM with all the rollbacks.
The main problem that I had was that I initially tried to name the property in the "Unset_AppName_Version_Cmd" CustomAction.
Thanks again to Kiran for all his help.