public/Invoke-PSJetInstaller.ps1
<# .SYNOPSIS Initiates the PSJet installer process, executing scripts sequentially with optional restarts and persistent state across restarts. .DESCRIPTION The `Invoke-PSJetInstaller` function orchestrates a sequential execution of installation step scripts, handling script state management, optional self-elevation for administrative privileges, and conditional system restarts with installation state persistence. When `EnableRestart` is specified, the function ensures that the installer continues from the last step after a system restart by registering a scheduled task to re-invoke the installer on user logon. The scheduled task will be unregistered upon successful installation completion. During the installation process, individual step scripts are executed in a sequential manner. Execution is achieved via "dot sourcing", which is a method of script execution that runs the script in the current scope. The dot sourcing technique is particularly relevant when scripts modify variables that must retain their changed values in the calling script. The method looks like this: . $ScriptPath This ensures any variables, functions, or other items defined or modified within the script persist in the calling script's scope after execution, maintaining state and functionality across the different phases of the installation process. .PARAMETER AsAdmin If specified, the installer attempts to self-elevate to run with administrative privileges using the `Invoke-ElevateAsAdmin` function. .PARAMETER EnableRestart If specified, enables handling of system restarts and ensures the installation continues from the last step by leveraging scheduled tasks, registered, and unregistered by `Register-PSJetInstallerScheduledTask` and `Unregister-PSJetInstallerScheduledTask` respectively. .EXAMPLE Invoke-PSJetInstaller -AsAdmin -EnableRestart Description ----------- Initiates the installer ensuring administrative privileges and enabling handling and persistence through system restarts. .NOTES - Installation step scripts should reside in "$installerDirectory\Steps\". - Scripts must be named to enforce execution order (e.g., 01-FirstStep.ps1, 02-SecondStep.ps1). - Step scripts use `Get-PSJetInstallerState` for state management and persistence across restarts. - A step script can request a system restart by assigning `$true` to `$state.restartComputer`. - User prompts on restart can be suppressed by assigning `$true` to `$state.autoRestartComputer`. - The `Invoke-ElevateAsAdmin`, `Register-PSJetInstallerScheduledTask`, and `Unregister-PSJetInstallerScheduledTask` functions should be defined and accessible within the scope of `Invoke-PSJetInstaller`. .OUTPUTS None. Outputs to host and might restart the computer, terminating the PowerShell session. .INPUTS None. All inputs are handled through parameters. #> function Invoke-PSJetInstaller { param ( [Parameter()] [switch]$AsAdmin, [Parameter()] [switch]$EnableRestart ) # Self-elevate the script if required if ($AsAdmin) { Invoke-ElevateAsAdmin } # Schedule the installer to run at logon if ($EnableRestart) { Register-PSJetInstallerScheduledTask } # Set state $state = Get-PSJetInstallerState $installerDirectory = Get-InvocationDirectory $steps = Get-ChildItem -Path "$installerDirectory\Steps\*.ps1" | Sort-Object FullName if ($null -eq $state.step) { $firstStep = $steps | Select-Object -First 1 | Select-Object -ExpandProperty FullName $state.step = $firstStep } $nextStep = $state.step while ($null -ne $nextStep) { # Set current step $currentStep = $nextStep # Execute current step via dot sourcing, ensuring persistence of variables and functions in the current scope . $currentStep # Determine next step $nextStep = ($steps | Where-Object FullName -gt $currentStep | Select-Object -First 1 | Select-Object -ExpandProperty FullName) $state.step = $nextStep # If the next step is null, the installation is complete if ($null -eq $nextStep) { break } # Restart computer if required if ($EnableRestart -and $state.restartComputer) { $state.restartComputer = $false Save-PSJetInstallerState Write-Warning 'The installer will continue after the computer is restarted. The computer will now restart.' -WarningAction Continue if (-Not $state.autoRestartComputer) { Show-KeyPressPrompt -Message 'Press any key to restart the computer...' } Restart-Computer -Force return } } if ($EnableRestart) { Unregister-PSJetInstallerScheduledTask } # Remove state $stateAppData = Get-PSJetInstallerAppData Remove-Item -Path $stateAppData.StateJsonPath -Force # Finish Write-Information 'The software installation is completed.' -InformationAction Continue Show-KeyPressPrompt -Message 'Press any key to finish...' } |