-
Notifications
You must be signed in to change notification settings - Fork 20
Description
When using SetupBuilder for packaging MSIs we often have the need to run a script as part of the installation, which is usually done via a custom action. While SetupBuilder already provides a means to run a script (or really any command) after the installer (via setupBuilder.runAfter), this runs asynchronously and is therefore not useful as part of the actual installation (especially if a failed execution should also fail the installation).
Normally this would be solved by using a custom WXS template with an added custom action:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product>
<CustomAction Id="afterInstScript"
ExeCommand="PowerShell.exe -ExecutionPolicy UnRestricted -File afterInst.ps1"
Directory="INSTALLDIR" Execute="deferred" Return="asyncWait"/>
<InstallExecuteSequence>
<Custom Action="afterInstScript" After="InstallFiles" />
</InstallExecuteSequence>
</Product>
</Wix>
To get rid of the additional WXS file I propose an extension to the msi-DSL to expose the relevant custom action and sequence parameters:
msi {
runCommand {
command = "cmd.exe /c echo done" // one of command || powershell (see below) is mandatory
before = "InstallInitialize" // mandatory, possibly with default
execute = "deferred" // mandatory, possibly with default
return = "asyncWait" // mandatory, possibly with default
}
}
These values would be passed through as-is to the respective attributes in the resulting WXS.
Since the most common use case of this nowadays (for us anyway) is to run a PowerShell script and there is no means to embbed one today, instead of command the following should be possible:
msi {
runCommand {
powershell { // one of command || powershell is mandatory
script = "" // mandatory
parameters = "" // optional
}
before = "InstallInitialize" // mandatory, possibly with default
execute = "deferred" // mandatory, possibly with default
return = "asyncWait" // mandatory, possibly with default
}
}
This would leverage PowerShell's encoded-command option to avoid hassling with temporary script files by using the script at the given path and the given parameters (optional) to construct an ExeCommand:
powershell.exe <parameters> –EncodedCommand <base64-encoded script>
If this proposal is accepted, I would take care of the implementation.