Skip to content

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

@mithomas

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions