using namespace Microsoft.Win32; $null = New-Module { . "$PSScriptRoot/../lib/Registry.ps1"; . "$PSScriptRoot/../../lib/Scripting.ps1"; [RegistryKey] $key = $null; $runOncePath = "Software\Microsoft\Windows\CurrentVersion\RunOnce"; $systemRunOncePath = "HKLM:\$runOncePath"; $logonPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" $runOnceName = "PortValhalla"; $powerSchemeOption = "PowerScheme"; $autologinOption = "AutoAdminLogon"; $domainOption = "DefaultDomainName"; $userOption = "DefaultUserName"; $passwordOption = "DefaultPassword"; <# .SYNOPSIS Gets the reghistry key containing the `RunOnce` commands. .PARAMETER UserKey The key of the user to get the `RunOnce` key for. #> function Get-RunOnceKey { param( [RegistryKey] $UserKey ) [string] $path = $null; if ($UserKey) { $path = Join-Path ($UserKey.PSPath) $runOncePath; } else { $path = $systemRunOncePath; } if (-not (Test-Path $path)) { New-Item $path; } else { Get-Item $path; } } <# .SYNOPSIS Generates a script for executing the installer. #> function Get-StartupScript { "pwsh -Command " + (Get-StartupCommand); } <# .SYNOPSIS Generates a command for running the installer using `pwsh`. #> function Get-StartupCommand { ($env:DEBUG ? "`$env:DEBUG = $([int]$env:DEBUG);" : "") + ($env:VALHALLA_ROOT ? "`$env:VALHALLA_ROOT = $(ConvertTo-Injection $env:VALHALLA_ROOT);" : "") + ($env:PWSH_PATH ? "`$env:PWSH_PATH = $(ConvertTo-Injection $env:PWSH_PATH);" : "") + ($env:BACKUP_ARCHIVE ? "`$env:BACKUP_ARCHIVE = $(ConvertTo-Injection ([System.IO.Path]::GetFullPath($env:BACKUP_ARCHIVE)));" : "") + "`$env:INSTALLER_SCRIPT = $(ConvertTo-Injection (Resolve-Path $env:INSTALLER_SCRIPT));" + "`$env:CONFIG_NAME = $(ConvertTo-Injection $env:CONFIG_NAME);" + "& `$env:INSTALLER_SCRIPT;"; } <# .SYNOPSIS Gets the GUID of the current power scheme. #> function Get-PowerScheme { [regex]::Match((powercfg /GETACTIVESCHEME), "Power Scheme GUID: ([0-9a-f-]+) ").Groups[1].Value; } <# .SYNOPSIS Sets the current power scheme. .PARAMETER SchemeID The ID of the scheme to set. #> function Set-PowerScheme { param( [string] $SchemeID ) powercfg /S $SchemeID; } <# .SYNOPSIS Backs up and overrides the current power scheme if it might cause automatic standby. #> function Backup-PowerScheme { $performanceScheme = "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"; $currentScheme = Get-PowerScheme; if ($currentScheme -ne $performanceScheme) { Write-Host "Disabling Power Save mode"; Set-SetupOption $powerSchemeOption $currentScheme; powercfg /S $performanceScheme; } } <# .SYNOPSIS Restores the backed up power scheme. #> function Restore-PowerScheme { $scheme = Get-SetupOption $powerSchemeOption; if ($scheme) { powercfg /S $scheme; } } <# .SYNOPSIS Registers a task to run the setup once after the next reboot. .PARAMETER UserKey The regtistry key of the user to register the task for. #> function Register-Setup { param( [Parameter(ParameterSetName = "System")] [switch] $System, [Parameter(ParameterSetName = "DefaultUser", Mandatory)] [switch] $DefaultUser, [Parameter(ParameterSetName = "User", Mandatory)] [switch] $User, [Parameter(ParameterSetName = "User")] [Parameter(ParameterSetName = "SpecificUser", Mandatory)] [RegistryKey] $UserKey ) if ($DefaultUser.IsPresent) { Edit-DefaultUserKey { param( [RegistryKey] $Key ) Register-Setup -UserKey $Key; } return; } if ($User.IsPresent -or $UserKey) { if (-not $UserKey) { $UserKey = Get-Item "HKCU:\"; } $key = Get-RunOnceKey $UserKey; } else { $key = Get-RunOnceKey; } Set-ItemProperty -Path $key.PSPath -Name $runOnceName -Type "ExpandString" -Value (Get-StartupScript); $key.Handle.Close(); } <# .SYNOPSIS Clears leftovers from past registrations. #> function Clear-SetupRegistration { Edit-DefaultUserKey { param( [RegistryKey] $Key ) $runOnceKey = Get-RunOnceKey $Key; Remove-Item $runOnceKey.PSPath; } } <# .SYNOPSIS Sets the user to login automatically on boot. .PARAMETER Name The name of the user to login automatically. #> function Set-AutologinUser { param( [string] $Name ) Set-ItemProperty $logonPath -Name $autologinOption "1"; if (-not $Name) { $Name = Get-SetupUser; } $options = @{ $domainOption = ""; $userOption = $Name; $passwordOption = ""; }; foreach ($key in $options.Keys) { Set-ItemProperty $logonPath -Name $key -Value $options[$key]; } } <# .SYNOPSIS Disables the automatic login. #> function Disable-Autologin { Set-ItemProperty $logonPath -Name $autologinOption "0"; foreach ($key in @($domainOption, $userOption, $passwordOption)) { Remove-ItemProperty $logonPath -Name $key -ErrorAction SilentlyContinue; } } <# .SYNOPSIS Reboots the machine intermediately and restarts the setup after the next login. #> function Restart-Intermediate { param( [Parameter(ParameterSetName = "None")] [switch] $NoRegister, [Parameter(ParameterSetName = "Default", Mandatory)] [switch] $DefaultUser, [Parameter(ParameterSetName = "Current", Mandatory)] [switch] $CurrentUser ) if (-not $NoRegister.IsPresent) { if ($DefaultUser.IsPresent) { Register-Setup -DefaultUser; } elseif ($CurrentUser.IsPresent) { Register-Setup -User; } else { Register-Setup; } } if ($env:DEBUG -and (-not $Global:NonInteractive)) { Read-Host "Press enter to reboot"; } Restart-Computer -Force; } }