. "$PSScriptRoot/Config.ps1"; . "$PSScriptRoot/Operations.ps1"; . "$PSScriptRoot/System.ps1"; . "$PSScriptRoot/../Types/InstallerAction.ps1"; $null = New-Module { . "$PSScriptRoot/../Types/InstallerAction.ps1"; $userArgument = "name"; function Start-SoftwareInstaller { param( [string] $Name, [switch] $Force, [scriptblock] $Base = $null, [scriptblock] $Backup = $null, [scriptblock] $Installer = $null, [scriptblock] $Configurator = $null, [scriptblock] $UserBackup = $null, [scriptblock] $UserConfigurator = $null, [string] $Inherit, [Parameter(Position = 0)] [Nullable[InstallerAction]] $Action, [Parameter(Position = 1)] [hashtable] $Arguments, [Parameter()] [hashtable] $Context ) [InstallerAction] $Action = & { if ($null -ne $Action) { $Action; } else { [InstallerAction]::Install; } }; if (-not $Name) { $Name = Split-Path -Leaf (Split-Path -Parent ((Get-PSCallStack)[1].ScriptName)); } if ($Inherit) { foreach ($script in @("Backup", "Installer", "Configurator", "UserBackup", "UserConfigurator")) { if (-not (Get-Variable $script).Value) { Set-Variable $script { param([switch]$Force) $parameters = $MyInvocation.UnboundArguments; if ($Force.ToBool()) { $parameters = $parameters + @("-Force"); } & $Inherit -Action $Action @parameters }; } } } Start-Operation { $installHandler = { param( [string] $Name, [switch] $Force, [InstallerAction] $Action, [hashtable] $Arguments, [hashtable] $Context ) [string] $DisplayName = $null; if ($null -ne $Name) { $DisplayName = "``$Name``"; } else { $DisplayName = "unknown software"; } $Arguments ??= @{ }; $Context ??= @{ }; $install = $Force -or (Test-Program "$Name"); $argumentList = @{ name = $Name; force = $Force; installer = $installHandler; arguments = $Arguments; context = $Context; base = { & "$Inherit" -Action $Action $args }; }; switch ($Action) { ([InstallerAction]::Backup) { if ($Backup -and $install) { Write-Host "Backing up $DisplayName…"; & $Backup @argumentList; } break; } ([InstallerAction]::Install) { if ($Installer -and $install) { Write-Host "Installing $DisplayName…"; & $Installer @argumentList; } & $installHandler @argumentList -Action ([InstallerAction]::Configure); if ($UserConfigurator -and (-not (Test-SetupUser))) { & $installHandler @argumentList -Action ([InstallerAction]::ConfigureUser); } break; } ([InstallerAction]::Configure) { if ($Configurator -and $install) { Write-Host "Configuring $DisplayName…"; & $Configurator @argumentList; } break; } default { if ((-not $Arguments.ContainsKey($userArgument)) -or (-not $Arguments[$userArgument])) { $Arguments.Remove($userArgument); $Arguments.Add($userArgument, ($IsWindows ? $env:UserName : $env:USER)); } $user = $Arguments[$userArgument]; $install = $Force -or (Test-Program -User $user "$Name"); switch ($_) { ([InstallerAction]::BackupUser) { if ($UserBackup -and $install) { Write-Host "Backing up $DisplayName for user ``$user``…"; & $UserBackup @argumentList; } } ([InstallerAction]::ConfigureUser) { if ($UserConfigurator -and $install) { Write-Host "Configuring $DisplayName for user ``$user``…"; & $UserConfigurator @argumentList; } } } break; } } }; & $installHandler -Name $Name -Force:$($Force.ToBool()) -Action $Action -Arguments $Arguments -Context $Context; }; } }