Run - Windows Installer

Octopus.Script exported 2019-11-07 by jzabroski belongs to ‘Windows’ category.

Runs the Windows Installer to non-interactively install an MSI

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Msi File Path

MsiFilePath =

This is the path of the MSI file that will be installed. If the path includes wildcards, then the first match will be used.

Action

Action = Install

The task to perform with the MSI, options include install, repair or remove.

Action Modifier

ActionModifier =

Use this to specify a different behavior for the Repair action

Properties

Properties = REBOOT=ReallySuppress

Properties that will be passed to the MSI separated by lines. Properties are in the format key=value, note that values with spaces in the must be quoted.

Key=Value
Key="Value"

Logging Options

LoggingOptions = *

One or more of:

[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*]
  • i - Status messages
  • w - Nonfatal warnings
  • e - All error messages
  • a - Start-up of actions
  • r - Action-specific records
  • u - User requests
  • c - Initial UI parameters
  • m - Out-of-memory or fatal exit information
  • o - Out-of-disk-space messages
  • p - Terminal properties
  • v - Verbose output
  • x - Extra debugging information
  • + - Append to existing log file
  • ! - Flush each line to the log
  • * - Log all information, except for v and x options

Log as artifact

LogAsArtifact = false

If selected, then return log output as an artifact. If unselected then return log output as inline content

Ignored Error Codes

IgnoredErrorCodes =

Use commas to separate integer values.

Script body

Steps based on this template will execute the following PowerShell script.

# Running outside octopus
param(
    [string]$MsiFilePath,
	[ValidateSet("Install", "Repair", "Remove", IgnoreCase=$true)]
	[string]$Action,
	[string]$ActionModifier,
    [string]$LoggingOptions = "*",
    [ValidateSet("False", "True")]
    [string]$LogAsArtifact,
	[string]$Properties,
	[int[]]$IgnoredErrorCodes,
    [switch]$WhatIf
) 

$ErrorActionPreference = "Stop"

$ErrorMessages = @{
	"0" = "Action completed successfully.";
	"13" = "The data is invalid.";
	"87" = "One of the parameters was invalid.";
	"1601" = "The Windows Installer service could not be accessed. Contact your support personnel to verify that the Windows Installer service is properly registered.";
	"1602" = "User cancel installation.";
	"1603" = "Fatal error during installation.";
	"1604" = "Installation suspended, incomplete.";
	"1605" = "This action is only valid for products that are currently installed.";
	"1606" = "Feature ID not registered.";
	"1607" = "Component ID not registered.";
	"1608" = "Unknown property.";
	"1609" = "Handle is in an invalid state.";
	"1610" = "The configuration data for this product is corrupt. Contact your support personnel.";
	"1611" = "Component qualifier not present.";
	"1612" = "The installation source for this product is not available. Verify that the source exists and that you can access it.";
	"1613" = "This installation package cannot be installed by the Windows Installer service. You must install a Windows service pack that contains a newer version of the Windows Installer service.";
	"1614" = "Product is uninstalled.";
	"1615" = "SQL query syntax invalid or unsupported.";
	"1616" = "Record field does not exist.";
	"1618" = "Another installation is already in progress. Complete that installation before proceeding with this install.";
	"1619" = "This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package.";
	"1620" = "This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package.";
	"1621" = "There was an error starting the Windows Installer service user interface. Contact your support personnel.";
	"1622" = "Error opening installation log file. Verify that the specified log file location exists and is writable.";
	"1623" = "This language of this installation package is not supported by your system.";
	"1624" = "Error applying transforms. Verify that the specified transform paths are valid.";
	"1625" = "This installation is forbidden by system policy. Contact your system administrator.";
	"1626" = "Function could not be executed.";
	"1627" = "Function failed during execution.";
	"1628" = "Invalid or unknown table specified.";
	"1629" = "Data supplied is of wrong type.";
	"1630" = "Data of this type is not supported.";
	"1631" = "The Windows Installer service failed to start. Contact your support personnel.";
	"1632" = "The temp folder is either full or inaccessible. Verify that the temp folder exists and that you can write to it.";
	"1633" = "This installation package is not supported on this platform. Contact your application vendor.";
	"1634" = "Component not used on this machine.";
	"1635" = "This patch package could not be opened. Verify that the patch package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer patch package.";
	"1636" = "This patch package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer patch package.";
	"1637" = "This patch package cannot be processed by the Windows Installer service. You must install a Windows service pack that contains a newer version of the Windows Installer service.";
	"1638" = "Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel.";
	"1639" = "Invalid command line argument. Consult the Windows Installer SDK for detailed command line help.";
	"1640" = "Installation from a Terminal Server client session not permitted for current user.";
	"1641" = "The installer has started a reboot.";
	"1642" = "The installer cannot install the upgrade patch because the program being upgraded may be missing, or the upgrade patch updates a different version of the program. Verify that the program to be upgraded exists on your computer and that you have the correct upgrade patch.";
	"3010" = "A restart is required to complete the install. This does not include installs where the ForceReboot action is run. Note that this error will not be available until future version of the installer."
};

function Get-Param($Name, [switch]$Required, $Default) {
    $result = $null

    if ($OctopusParameters -ne $null) {
        $result = $OctopusParameters[$Name]
    }

    if ($result -eq $null) {
        $variable = Get-Variable $Name -EA SilentlyContinue   
        if ($variable -ne $null) {
            $result = $variable.Value
        }
    }

    if ($result -eq $null) {
        if ($Required) {
            throw "Missing parameter value $Name"
        } else {
            $result = $Default
        }
    }

    return $result
}

function Resolve-PotentialPath($Path) {
	[Environment]::CurrentDirectory = $pwd
	return [IO.Path]::GetFullPath($Path)
}

function Get-LogOptionFile($msiFile, $streamLog) {
	$logPath = Resolve-PotentialPath "$msiFile.log"
	
	if (Test-Path $logPath) {
		Remove-Item $logPath
	}
	
	return $logPath
}

function Exec
{
    [CmdletBinding()]
    param(
        [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,
        [string]$errorMessage = ($msgs.error_bad_command -f $cmd),
		[switch]$ReturnCode
    )

	$lastexitcode = 0
    & $cmd
	
	if ($ReturnCode) {
		return $lastexitcode
	} else  {
		if ($lastexitcode -ne 0) {
			throw ("Exec: " + $errorMessage)
		}		
	}
}

function Wrap-Arguments($Arguments)
{
	return $Arguments | % { 
		
		[string]$val = $_
		
		#calling msiexec fails when arguments are quoted
		if (($val.StartsWith("/") -and $val.IndexOf(" ") -eq -1) -or ($val.IndexOf("=") -ne -1) -or ($val.IndexOf('"') -ne -1)) {
			return $val
		}
	
		return '"{0}"' -f $val
	}
}

function Start-Process2($FilePath, $ArgumentList, [switch]$showCall, [switch]$whatIf)
{
	$ArgumentListString = (Wrap-Arguments $ArgumentList) -Join " "

	$pinfo = New-Object System.Diagnostics.ProcessStartInfo
	$pinfo.FileName = $FilePath
	$pinfo.UseShellExecute = $false
	$pinfo.CreateNoWindow = $true
	$pinfo.RedirectStandardOutput = $true
	$pinfo.RedirectStandardError = $true
	$pinfo.Arguments = $ArgumentListString;
	$pinfo.WorkingDirectory = $pwd

	$exitCode = 0
	
	if (!$whatIf) {
	
		if ($showCall) {
			$x = Write-Output "$FilePath $ArgumentListString"
		}
		
		$p = New-Object System.Diagnostics.Process
		$p.StartInfo = $pinfo
		$started = $p.Start()
		$p.WaitForExit()

		$stdout = $p.StandardOutput.ReadToEnd()
		$stderr = $p.StandardError.ReadToEnd()
		$x = Write-Output $stdout
		$x = Write-Output $stderr
		
		$exitCode = $p.ExitCode
	} else {
		Write-Output "skipping: $FilePath $ArgumentListString"
	}
	
	return $exitCode
}

function Get-EscapedFilePath($FilePath)
{
    return [Management.Automation.WildcardPattern]::Escape($FilePath)
}

& {
    param(
        [string]$MsiFilePath,
		[string]$Action,
		[string]$ActionModifier,
        [string]$LoggingOptions,
        [bool]$LogAsArtifact,
		[string]$Properties,
		[int[]]$IgnoredErrorCodes
    ) 

    $MsiFilePathLeaf = Split-Path -Path $MsiFilePath -Leaf
    $EscapedMsiFilePath = Get-EscapedFilePath (Split-Path -Path $MsiFilePath)
    
	$MsiFilePath = Get-EscapedFilePath (Resolve-Path "$EscapedMsiFilePath\$MsiFilePathLeaf" | Select-Object -First 1).ProviderPath

    Write-Output "Installing MSI"
    Write-Host " MsiFilePath: $MsiFilePath" -f Gray
	Write-Host " Action: $Action" -f Gray
	Write-Host " Properties: $Properties" -f Gray
	Write-Host

	if ((Get-Command msiexec) -Eq $Null) {
		throw "Command msiexec could not be found"
	}
	
	if (!(Test-Path $MsiFilePath)) {
		throw "Could not find the file $MsiFilePath"
	}

	$actions = @{
		"Install" = "/i";
		"Repair" = "/f";
		"Remove" = "/x";
	};
	
	$actionOption = $actions[$action]
	$actionOptionFile = $MsiFilePath
	if ($ActionModifier)
	{
		$actionOption += $ActionModifier
	}
	
    if ($LoggingOptions) {
	    $logOption = "/L$LoggingOptions"
	    $logOptionFile = Get-LogOptionFile $MsiFilePath
	}
	$quiteOption = "/qn"
	$noRestartOption = "/norestart"
	
	$parameterOptions = $Properties -Split "\r\n?|\n" | ? { !([string]::IsNullOrEmpty($_)) } | % { $_.Trim() }
	
	$options = @($actionOption, $actionOptionFile, $logOption, $logOptionFile, $quiteOption, $noRestartOption) + $parameterOptions

	$exePath = "msiexec.exe"

	$exitCode = Start-Process2 -FilePath $exePath -ArgumentList $options -whatIf:$whatIf -ShowCall
	
	Write-Output "Exit Code was! $exitCode"
	
	if (Test-Path $logOptionFile) {

		Write-Output "Reading installer log"

        # always write out these (http://robmensching.com/blog/posts/2010/8/2/the-first-thing-i-do-with-an-msi-log/)
        (Get-Content $logOptionFile) | Select-String -SimpleMatch "value 3" -Context 10,0 | ForEach-Object { Write-Warning $_ }

        if ($LogAsArtifact) {
            New-OctopusArtifact -Path $logOptionFile -Name "$Action-$([IO.Path]::GetFileNameWithoutExtension($MsiFilePath)).log"
        } else {
	    	Get-Content $logOptionFile | Write-Output
        }

	} else {
		Write-Output "No logs were generated"
	}

	if ($exitCode -Ne 0) {
		$errorCodeString = $exitCode.ToString()
		$errorMessage = $ErrorMessages[$errorCodeString]
		
		if ($IgnoredErrorCodes -notcontains $exitCode) {

			throw "Error code $exitCodeString was returned: $errorMessage"
		}
		else {
			Write-Output "Error code [$exitCodeString] was ignored because it was in the IgnoredErrorCodes [$($IgnoredErrorCodes -join ',')] parameter. Error Message [$errorMessage]"
		}
	}
	
} `
(Get-Param 'MsiFilePath' -Required) `
(Get-Param 'Action' -Required) `
(Get-Param 'ActionModifier') `
(Get-Param 'LoggingOptions') `
((Get-Param 'LogAsArtifact') -eq "True") `
(Get-Param 'Properties') `
(Get-Param 'IgnoredErrorCodes')

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "f56647ac-7762-4986-bc98-c3fb74bb844f",
  "Name": "Run - Windows Installer",
  "Description": "Runs the Windows Installer to non-interactively install an MSI",
  "Version": 13,
  "ExportedAt": "2019-11-07T16:37:00.415Z",
  "ActionType": "Octopus.Script",
  "Author": "jzabroski",
  "Packages": [],
  "Parameters": [
    {
      "Id": "381f31f3-2cad-45fa-96ea-d99b2299667c",
      "Name": "MsiFilePath",
      "Label": "Msi File Path",
      "HelpText": "This is the path of the MSI file that will be installed. If the path includes wildcards, then the first match will be used.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "6e056c08-d73e-4e3e-bf45-c12e0d3d1d24",
      "Name": "Action",
      "Label": "Action",
      "HelpText": "The task to perform with the MSI, options include install, repair or remove.",
      "DefaultValue": "Install",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "Install\nRepair\nRemove"
      }
    },
    {
      "Id": "7343a832-0673-472c-ae8f-1a328d65cafe",
      "Name": "ActionModifier",
      "Label": "Action Modifier",
      "HelpText": "Use this to specify a different behavior for the Repair action",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "698d3bfb-2c14-4783-aa19-2a2ae2f49645",
      "Name": "Properties",
      "Label": "Properties",
      "HelpText": "Properties that will be passed to the MSI separated by lines. Properties are in the format key=value, note that values with spaces in the must be quoted. \n\n    Key=Value\n    Key=\"Value\"",
      "DefaultValue": "REBOOT=ReallySuppress",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Id": "d78748d0-2f38-485d-b76e-c41e5dbde429",
      "Name": "LoggingOptions",
      "Label": "Logging Options",
      "HelpText": "One or more of:\n\n    [i|w|e|a|r|u|c|m|o|p|v|x|+|!|*]\n\n-  i - Status messages\n-  w - Nonfatal warnings\n-  e - All error messages\n-  a - Start-up of actions\n-  r - Action-specific records\n-  u - User requests\n-  c - Initial UI parameters\n-  m - Out-of-memory or fatal exit information\n-  o - Out-of-disk-space messages\n-  p - Terminal properties\n-  v - Verbose output\n-  x - Extra debugging information\n-  \\+ - Append to existing log file\n-  ! - Flush each line to the log\n-  \\* - Log all information, except for v and x options",
      "DefaultValue": "*",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "532b5a46-9510-4558-a17c-a580153fbaff",
      "Name": "LogAsArtifact",
      "Label": "Log as artifact",
      "HelpText": "If selected, then return log output as an artifact.\nIf unselected then return log output as inline content",
      "DefaultValue": "false",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "dc10c5e9-d988-4136-9f3e-c0c881a103b3",
      "Name": "IgnoredErrorCodes",
      "Label": "Ignored Error Codes",
      "HelpText": "Use commas to separate integer values.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptBody": "# Running outside octopus\nparam(\n    [string]$MsiFilePath,\n\t[ValidateSet(\"Install\", \"Repair\", \"Remove\", IgnoreCase=$true)]\n\t[string]$Action,\n\t[string]$ActionModifier,\n    [string]$LoggingOptions = \"*\",\n    [ValidateSet(\"False\", \"True\")]\n    [string]$LogAsArtifact,\n\t[string]$Properties,\n\t[int[]]$IgnoredErrorCodes,\n    [switch]$WhatIf\n) \n\n$ErrorActionPreference = \"Stop\"\n\n$ErrorMessages = @{\n\t\"0\" = \"Action completed successfully.\";\n\t\"13\" = \"The data is invalid.\";\n\t\"87\" = \"One of the parameters was invalid.\";\n\t\"1601\" = \"The Windows Installer service could not be accessed. Contact your support personnel to verify that the Windows Installer service is properly registered.\";\n\t\"1602\" = \"User cancel installation.\";\n\t\"1603\" = \"Fatal error during installation.\";\n\t\"1604\" = \"Installation suspended, incomplete.\";\n\t\"1605\" = \"This action is only valid for products that are currently installed.\";\n\t\"1606\" = \"Feature ID not registered.\";\n\t\"1607\" = \"Component ID not registered.\";\n\t\"1608\" = \"Unknown property.\";\n\t\"1609\" = \"Handle is in an invalid state.\";\n\t\"1610\" = \"The configuration data for this product is corrupt. Contact your support personnel.\";\n\t\"1611\" = \"Component qualifier not present.\";\n\t\"1612\" = \"The installation source for this product is not available. Verify that the source exists and that you can access it.\";\n\t\"1613\" = \"This installation package cannot be installed by the Windows Installer service. You must install a Windows service pack that contains a newer version of the Windows Installer service.\";\n\t\"1614\" = \"Product is uninstalled.\";\n\t\"1615\" = \"SQL query syntax invalid or unsupported.\";\n\t\"1616\" = \"Record field does not exist.\";\n\t\"1618\" = \"Another installation is already in progress. Complete that installation before proceeding with this install.\";\n\t\"1619\" = \"This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package.\";\n\t\"1620\" = \"This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package.\";\n\t\"1621\" = \"There was an error starting the Windows Installer service user interface. Contact your support personnel.\";\n\t\"1622\" = \"Error opening installation log file. Verify that the specified log file location exists and is writable.\";\n\t\"1623\" = \"This language of this installation package is not supported by your system.\";\n\t\"1624\" = \"Error applying transforms. Verify that the specified transform paths are valid.\";\n\t\"1625\" = \"This installation is forbidden by system policy. Contact your system administrator.\";\n\t\"1626\" = \"Function could not be executed.\";\n\t\"1627\" = \"Function failed during execution.\";\n\t\"1628\" = \"Invalid or unknown table specified.\";\n\t\"1629\" = \"Data supplied is of wrong type.\";\n\t\"1630\" = \"Data of this type is not supported.\";\n\t\"1631\" = \"The Windows Installer service failed to start. Contact your support personnel.\";\n\t\"1632\" = \"The temp folder is either full or inaccessible. Verify that the temp folder exists and that you can write to it.\";\n\t\"1633\" = \"This installation package is not supported on this platform. Contact your application vendor.\";\n\t\"1634\" = \"Component not used on this machine.\";\n\t\"1635\" = \"This patch package could not be opened. Verify that the patch package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer patch package.\";\n\t\"1636\" = \"This patch package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer patch package.\";\n\t\"1637\" = \"This patch package cannot be processed by the Windows Installer service. You must install a Windows service pack that contains a newer version of the Windows Installer service.\";\n\t\"1638\" = \"Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel.\";\n\t\"1639\" = \"Invalid command line argument. Consult the Windows Installer SDK for detailed command line help.\";\n\t\"1640\" = \"Installation from a Terminal Server client session not permitted for current user.\";\n\t\"1641\" = \"The installer has started a reboot.\";\n\t\"1642\" = \"The installer cannot install the upgrade patch because the program being upgraded may be missing, or the upgrade patch updates a different version of the program. Verify that the program to be upgraded exists on your computer and that you have the correct upgrade patch.\";\n\t\"3010\" = \"A restart is required to complete the install. This does not include installs where the ForceReboot action is run. Note that this error will not be available until future version of the installer.\"\n};\n\nfunction Get-Param($Name, [switch]$Required, $Default) {\n    $result = $null\n\n    if ($OctopusParameters -ne $null) {\n        $result = $OctopusParameters[$Name]\n    }\n\n    if ($result -eq $null) {\n        $variable = Get-Variable $Name -EA SilentlyContinue   \n        if ($variable -ne $null) {\n            $result = $variable.Value\n        }\n    }\n\n    if ($result -eq $null) {\n        if ($Required) {\n            throw \"Missing parameter value $Name\"\n        } else {\n            $result = $Default\n        }\n    }\n\n    return $result\n}\n\nfunction Resolve-PotentialPath($Path) {\n\t[Environment]::CurrentDirectory = $pwd\n\treturn [IO.Path]::GetFullPath($Path)\n}\n\nfunction Get-LogOptionFile($msiFile, $streamLog) {\n\t$logPath = Resolve-PotentialPath \"$msiFile.log\"\n\t\n\tif (Test-Path $logPath) {\n\t\tRemove-Item $logPath\n\t}\n\t\n\treturn $logPath\n}\n\nfunction Exec\n{\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,\n        [string]$errorMessage = ($msgs.error_bad_command -f $cmd),\n\t\t[switch]$ReturnCode\n    )\n\n\t$lastexitcode = 0\n    & $cmd\n\t\n\tif ($ReturnCode) {\n\t\treturn $lastexitcode\n\t} else  {\n\t\tif ($lastexitcode -ne 0) {\n\t\t\tthrow (\"Exec: \" + $errorMessage)\n\t\t}\t\t\n\t}\n}\n\nfunction Wrap-Arguments($Arguments)\n{\n\treturn $Arguments | % { \n\t\t\n\t\t[string]$val = $_\n\t\t\n\t\t#calling msiexec fails when arguments are quoted\n\t\tif (($val.StartsWith(\"/\") -and $val.IndexOf(\" \") -eq -1) -or ($val.IndexOf(\"=\") -ne -1) -or ($val.IndexOf('\"') -ne -1)) {\n\t\t\treturn $val\n\t\t}\n\t\n\t\treturn '\"{0}\"' -f $val\n\t}\n}\n\nfunction Start-Process2($FilePath, $ArgumentList, [switch]$showCall, [switch]$whatIf)\n{\n\t$ArgumentListString = (Wrap-Arguments $ArgumentList) -Join \" \"\n\n\t$pinfo = New-Object System.Diagnostics.ProcessStartInfo\n\t$pinfo.FileName = $FilePath\n\t$pinfo.UseShellExecute = $false\n\t$pinfo.CreateNoWindow = $true\n\t$pinfo.RedirectStandardOutput = $true\n\t$pinfo.RedirectStandardError = $true\n\t$pinfo.Arguments = $ArgumentListString;\n\t$pinfo.WorkingDirectory = $pwd\n\n\t$exitCode = 0\n\t\n\tif (!$whatIf) {\n\t\n\t\tif ($showCall) {\n\t\t\t$x = Write-Output \"$FilePath $ArgumentListString\"\n\t\t}\n\t\t\n\t\t$p = New-Object System.Diagnostics.Process\n\t\t$p.StartInfo = $pinfo\n\t\t$started = $p.Start()\n\t\t$p.WaitForExit()\n\n\t\t$stdout = $p.StandardOutput.ReadToEnd()\n\t\t$stderr = $p.StandardError.ReadToEnd()\n\t\t$x = Write-Output $stdout\n\t\t$x = Write-Output $stderr\n\t\t\n\t\t$exitCode = $p.ExitCode\n\t} else {\n\t\tWrite-Output \"skipping: $FilePath $ArgumentListString\"\n\t}\n\t\n\treturn $exitCode\n}\n\nfunction Get-EscapedFilePath($FilePath)\n{\n    return [Management.Automation.WildcardPattern]::Escape($FilePath)\n}\n\n& {\n    param(\n        [string]$MsiFilePath,\n\t\t[string]$Action,\n\t\t[string]$ActionModifier,\n        [string]$LoggingOptions,\n        [bool]$LogAsArtifact,\n\t\t[string]$Properties,\n\t\t[int[]]$IgnoredErrorCodes\n    ) \n\n    $MsiFilePathLeaf = Split-Path -Path $MsiFilePath -Leaf\n    $EscapedMsiFilePath = Get-EscapedFilePath (Split-Path -Path $MsiFilePath)\n    \n\t$MsiFilePath = Get-EscapedFilePath (Resolve-Path \"$EscapedMsiFilePath\\$MsiFilePathLeaf\" | Select-Object -First 1).ProviderPath\n\n    Write-Output \"Installing MSI\"\n    Write-Host \" MsiFilePath: $MsiFilePath\" -f Gray\n\tWrite-Host \" Action: $Action\" -f Gray\n\tWrite-Host \" Properties: $Properties\" -f Gray\n\tWrite-Host\n\n\tif ((Get-Command msiexec) -Eq $Null) {\n\t\tthrow \"Command msiexec could not be found\"\n\t}\n\t\n\tif (!(Test-Path $MsiFilePath)) {\n\t\tthrow \"Could not find the file $MsiFilePath\"\n\t}\n\n\t$actions = @{\n\t\t\"Install\" = \"/i\";\n\t\t\"Repair\" = \"/f\";\n\t\t\"Remove\" = \"/x\";\n\t};\n\t\n\t$actionOption = $actions[$action]\n\t$actionOptionFile = $MsiFilePath\n\tif ($ActionModifier)\n\t{\n\t\t$actionOption += $ActionModifier\n\t}\n\t\n    if ($LoggingOptions) {\n\t    $logOption = \"/L$LoggingOptions\"\n\t    $logOptionFile = Get-LogOptionFile $MsiFilePath\n\t}\n\t$quiteOption = \"/qn\"\n\t$noRestartOption = \"/norestart\"\n\t\n\t$parameterOptions = $Properties -Split \"\\r\\n?|\\n\" | ? { !([string]::IsNullOrEmpty($_)) } | % { $_.Trim() }\n\t\n\t$options = @($actionOption, $actionOptionFile, $logOption, $logOptionFile, $quiteOption, $noRestartOption) + $parameterOptions\n\n\t$exePath = \"msiexec.exe\"\n\n\t$exitCode = Start-Process2 -FilePath $exePath -ArgumentList $options -whatIf:$whatIf -ShowCall\n\t\n\tWrite-Output \"Exit Code was! $exitCode\"\n\t\n\tif (Test-Path $logOptionFile) {\n\n\t\tWrite-Output \"Reading installer log\"\n\n        # always write out these (http://robmensching.com/blog/posts/2010/8/2/the-first-thing-i-do-with-an-msi-log/)\n        (Get-Content $logOptionFile) | Select-String -SimpleMatch \"value 3\" -Context 10,0 | ForEach-Object { Write-Warning $_ }\n\n        if ($LogAsArtifact) {\n            New-OctopusArtifact -Path $logOptionFile -Name \"$Action-$([IO.Path]::GetFileNameWithoutExtension($MsiFilePath)).log\"\n        } else {\n\t    \tGet-Content $logOptionFile | Write-Output\n        }\n\n\t} else {\n\t\tWrite-Output \"No logs were generated\"\n\t}\n\n\tif ($exitCode -Ne 0) {\n\t\t$errorCodeString = $exitCode.ToString()\n\t\t$errorMessage = $ErrorMessages[$errorCodeString]\n\t\t\n\t\tif ($IgnoredErrorCodes -notcontains $exitCode) {\n\n\t\t\tthrow \"Error code $exitCodeString was returned: $errorMessage\"\n\t\t}\n\t\telse {\n\t\t\tWrite-Output \"Error code [$exitCodeString] was ignored because it was in the IgnoredErrorCodes [$($IgnoredErrorCodes -join ',')] parameter. Error Message [$errorMessage]\"\n\t\t}\n\t}\n\t\n} `\n(Get-Param 'MsiFilePath' -Required) `\n(Get-Param 'Action' -Required) `\n(Get-Param 'ActionModifier') `\n(Get-Param 'LoggingOptions') `\n((Get-Param 'LogAsArtifact') -eq \"True\") `\n(Get-Param 'Properties') `\n(Get-Param 'IgnoredErrorCodes')\n",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.RunOnServer": "false"
  },
  "Category": "Windows",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/run-windows-installer.json",
  "Website": "/step-templates/f56647ac-7762-4986-bc98-c3fb74bb844f",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////Da3qSsLvhtb0wur6O7zuWcfxldv2aMzyK7ftpOD3s+X48Pr+0fD7d9HzHLLr4fX8xD/OcwAAAaNJREFUeNrs3cFygjAUQFECWott1f//2sJoW6kIKEzNs+euXOmcmSSGDa8oJEmSJEmSJGmsj1W1K9cpsGD1Vr2WdToVEPC+2lYvZfpVrEW0qZpF1F+MRdRugzoNlvkiarfBPk0pT8GhWUSX2yASpDlLr2+DEJBmEY1ug6whx7N0n2b30G1QlmmxHsRYp6X76yvF9vg5RYQczq8UVURI35UiFmTgShED0p6lI1eKzCHTrxS5Qk6PZ9PLDtJ9PIsJmXWlyAky6/dAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQMJCyjltF/iO3gpJUpD8s4OAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8T8itwwKyhbTdMr4ha8hXUwZqhICcOgyNOIkE+V5wo4MSgr1u/fp7poO+AL8K/gL8yw0UeyRB34m9iQ/pVD8L5JYTO3NI58R+AsiEEzsW5OfE3sUe/zRwYkeGnG2g2CPS7rhjF4GKP0ZwyoldxK37kFqEL/7wU0mSJEmSJOmJ+xRgAHxZTCXGdZkfAAAAAElFTkSuQmCC",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Thursday, November 7, 2019