Skip to content

DSL-Extension for MSI-embedded (PowerShell-)script? #59

Description

@mithomas

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions