WIX CustomAction terminates with error 1721 or 1722 - wix

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.

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?

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.

prop.exe elevated execution in Wix

This question seems to have been answered ad nauseam on this web site but I cannot get Wix to run an exe with Administrator rights (Windows 8.1 64-bit).
The installer I develop copies the prop.exe utility (http://prop.codeplex.com/) to a folder under Program Files (appfolder) as well as a file (my_file.propdesc) which needs to be registered/unregistered by prop.exe like:
prop schema register my_file.propdesc (at the end of installation)
prop schema unregister my_file (at the beginning of uninstallation)
These two command lines need to be run with Administrator privileges. Because these should also be run without a command prompt, I've used CAQuietExec with another CustomAction preparing the argument for CAQuietExec (prop.exe is 32-bit so it's CAQuietExec instead of CAQuietExec64 if I am not mistaken).
<CustomAction Id='PropReg_Prep' Property='PropReg' Value='"[appfolder]prop.exe" schema register "[appfolder]my_file.propdesc"' Execute='immediate' />
<CustomAction Id='PropUnReg_Prep' Property='PropUnReg' Value='"[appfolder]prop.exe" schema unregister "[appfolder]my_file.propdesc"' Execute='immediate' />
<CustomAction Id="PropReg" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no" />
<CustomAction Id="PropUnReg" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no" />
The custom actions are executed as per:
<InstallExecuteSequence>
<Custom Action="PropReg_Prep" After="CostFinalize" >NOT Installed</Custom>
<Custom Action="PropUnReg_Prep" After="CostFinalize" >Installed</Custom>
<Custom Action="PropUnReg" After="InstallInitialize" >Installed</Custom>
<Custom Action="PropReg" After="InstallFiles" >NOT Installed</Custom>
</InstallExecuteSequence>
I cannot get prop to register/unregister my_file.propdesc. Could someone help?
You are scheduling the actions as Execute='immediate' this runs as the user that executes the installer.
Switch to using Execute='deferred' this will run as the system account. Assuming that the prop.exe doesn't require a full profile to run this should work.
When you're not impersonating you're running with the system account, that's got admin privileges but if you are expecting it to be a user account then there might be issues.
The thing that looks weird to me is that [appfolder]prop.exe for a number of reasons. It doesn't look like a proper application folder, so make sure it's correct. It also needs to be in uppercase, making it a public property, and you should mark it Secure="yes" in the property element. The issue is that it may not get properly transferred from your immediate CA into the execute sequence where it's used.
p.s. Do the install creating a verbose log so you can see how those directory vales are actually being resolved at run time.

Elevated custom action before removing files

I'm trying to write an Installer for my Windows Service using WiX. My executable can register/unregister itself as a Windows Service using the command line parameters --install and --uninstall. This is what I came up with:
<CustomAction Id='InstallAsService' FileKey='CCWirelessServer.exe' ExeCommand='--install' Return='check' Impersonate='no' Execute='deferred' />
<CustomAction Id='InstallAsServiceRollback' FileKey='CCWirelessServer.exe' ExeCommand='--uninstall' Return='check' Impersonate='no' Execute='rollback' />
<CustomAction Id='UninstallAsService' FileKey='CCWirelessServer.exe' ExeCommand='--uninstall' Return='check' Impersonate='no' Execute='deferred' />
<InstallExecuteSequence>
<Custom Action='InstallAsService' After='InstallFiles' >NOT Installed</Custom>
<Custom Action='InstallAsServiceRollback' Before='InstallAsService' >NOT Installed</Custom>
<Custom Action='UninstallAsService' Before='RemoveFiles' >Installed</Custom>
</InstallExecuteSequence>
Both install and uninstall basically work. But during uninstall I get the following message:
The setup must update files or services that cannot be updated while the system is running. If you choose to continue, a reboot will be required to complete the setup.
Despite this error message, the service gets unregistered and the files are deleted without a reboot. To me this looks like the installer is checking if CCWirelessServer.exe is opened before it executes my custom action.
So my question is: How do I need to modify my install execute sequence so that this error message does no longer appear?
If you are developing for Windows Installer > 3.1 you can take a look at the MSIRESTARTMANAGERCONTROL-property to see if it it set properly or if other values would would stop displaying the message.
I could suppress the message using the following values:
<Property Id="MSIRESTARTMANAGERCONTROL" Value="Disable" Secure="yes" />

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.