From 9ea7d31053089f2a7b6bc48877d6e5016a680aa9 Mon Sep 17 00:00:00 2001 From: Manuel Thalmann Date: Sun, 28 Jul 2024 20:52:07 +0200 Subject: [PATCH] Nest Windows setup in a function --- scripts/Windows/OS/Setup.ps1 | 134 ++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/scripts/Windows/OS/Setup.ps1 b/scripts/Windows/OS/Setup.ps1 index 395e0413..f10efc0a 100644 --- a/scripts/Windows/OS/Setup.ps1 +++ b/scripts/Windows/OS/Setup.ps1 @@ -1,74 +1,78 @@ #!/bin/pwsh -$Global:InformationPreference = "Continue"; -$Global:ErrorActionPreference = "Inquire"; -$null = $env:WIN_COMPUTER_NAME; -$null = $env:SETUP_SCRIPT_NAME; -$null = $env:CONFIG_MODULE; +function Start-Setup { + $Global:InformationPreference = "Continue"; + $Global:ErrorActionPreference = "Inquire"; + $null = $env:WIN_COMPUTER_NAME; + $null = $env:SETUP_SCRIPT_NAME; + $null = $env:CONFIG_MODULE; -$config = ConvertFrom-Json (Get-Content "$env:CONFIG_MODULE.json"); + $config = ConvertFrom-Json (Get-Content "$env:CONFIG_MODULE.json"); -[xml]$unattendedConfig = [xml]::new(); -$unattendedConfig.PreserveWhitespace = $true; + [xml]$unattendedConfig = [xml]::new(); + $unattendedConfig.PreserveWhitespace = $true; -$readerSettings = [System.Xml.XmlReaderSettings]::new(); -$readerSettings.IgnoreComments = $true; -$reader = [System.Xml.XmlReader]::Create("$PSScriptRoot/../Resources/Autounattend.template.xml", $readerSettings); + $readerSettings = [System.Xml.XmlReaderSettings]::new(); + $readerSettings.IgnoreComments = $true; + $reader = [System.Xml.XmlReader]::Create("$PSScriptRoot/../Resources/Autounattend.template.xml", $readerSettings); -$unattendedConfig.Load($reader); -$namespace = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $unattendedConfig.NameTable; -$namespace.AddNamespace("ua", $unattendedConfig.DocumentElement.NamespaceURI); + $unattendedConfig.Load($reader); + $namespace = New-Object -TypeName "Xml.XmlNamespaceManager" -ArgumentList $unattendedConfig.NameTable; + $namespace.AddNamespace("ua", $unattendedConfig.DocumentElement.NamespaceURI); -function Get-PassSettings { - [OutputType([xml])] - param( - [string] $passName - ) + function Get-PassSettings { + [OutputType([xml])] + param( + [string] $passName + ) - return $unattendedConfig.SelectSingleNode("/ua:unattend/ua:settings[@pass='$passName']", $namespace); + return $unattendedConfig.SelectSingleNode("/ua:unattend/ua:settings[@pass='$passName']", $namespace); + } + + function Get-RemoteScriptPath($path) { + $relativePath = [System.IO.Path]::GetRelativePath("$PSScriptRoot/../../..", $path); + Join-Path $env:REMOTE_PROJECT_PATH $relativePath; + } + + function Get-Injection($value) { + "([System.Text.Encoding]::Default.GetString([System.Convert]::FromBase64String('$( + [System.Convert]::ToBase64String([System.Text.Encoding]::Default.GetBytes($value)) + )')))" + } + + function Get-ScriptPathInjection($path) { + "(Join-Path `$env:SystemDrive $(Get-Injection (Get-RemoteScriptPath $path)))" + } + + # Adjust unattended settings + $specializeSettings = Get-PassSettings "specialize"; + $specializeSettings.SelectSingleNode("./ua:component[@name='Microsoft-Windows-Shell-Setup']/ua:ComputerName", $namespace).InnerText = "$env:WIN_COMPUTER_NAME"; + + # Execute corresponding installer script after startup + $oobeSystemSettings = Get-PassSettings "oobeSystem"; + $installationCommand = $oobeSystemSettings.SelectSingleNode("./ua:component/ua:FirstLogonCommands/ua:SynchronousCommand[last()]", $namespace); + $newCommand = $installationCommand.ParentNode.AppendChild($installationCommand.CloneNode($true)); + + $newCommand.SelectSingleNode("./ua:CommandLine", $namespace).InnerText = ` + "powershell -Command " + ` + "`$env:INSTALLER_SCRIPT = $(Get-ScriptPathInjection $env:SETUP_SCRIPT_NAME);" + ` + "`$env:CONFIG_MODULE = $(Get-ScriptPathInjection $env:CONFIG_MODULE);" + ` + "Invoke-Expression $(Get-ScriptPathInjection "$PSScriptRoot/InitialBoot.ps1");"; + + $orderElement = $newCommand.SelectSingleNode("./ua:Order", $namespace); + $orderElement.InnerText = ([int]($orderElement.InnerText) + 1); + $newCommand.SelectSingleNode("./ua:Description", $namespace).InnerText = "Install PowerShell Core and git and run setup script"; + + if (Get-Command Initialize-SetupConfig -ErrorAction SilentlyContinue) { + Initialize-SetupConfig $unattendedConfig $namespace; + } + + $unattendedConfigFile = "X:\unattend.xml"; + $unattendedConfig.PreserveWhitespace = $true; + $unattendedConfig.Save($unattendedConfigFile); + + Write-Warning "Attention: This program will completely wipe your current disk #1 and install Windows on it. Are you sure you want to do this?" + Read-Host -Prompt "Hit enter to continue or CTRL+C to abort" + & "$SETUP_DRIVE\setup.exe" /Unattend:$unattendedConfigFile; } -# Adjust unattended settings -$specializeSettings = Get-PassSettings "specialize"; -$specializeSettings.SelectSingleNode("./ua:component[@name='Microsoft-Windows-Shell-Setup']/ua:ComputerName", $namespace).InnerText = "$env:WIN_COMPUTER_NAME"; - -# Execute corresponding installer script after startup -$oobeSystemSettings = Get-PassSettings "oobeSystem"; -$installationCommand = $oobeSystemSettings.SelectSingleNode("./ua:component/ua:FirstLogonCommands/ua:SynchronousCommand[last()]", $namespace); -$newCommand = $installationCommand.ParentNode.AppendChild($installationCommand.CloneNode($true)); - -function Get-RemoteScriptPath($path) { - $relativePath = [System.IO.Path]::GetRelativePath("$PSScriptRoot/../../..", $path); - Join-Path $env:REMOTE_PROJECT_PATH $relativePath; -} - -function Get-Injection($value) { - "([System.Text.Encoding]::Default.GetString([System.Convert]::FromBase64String('$( - [System.Convert]::ToBase64String([System.Text.Encoding]::Default.GetBytes($value)) - )')))" -} - -function Get-ScriptPathInjection($path) { - "(Join-Path `$env:SystemDrive $(Get-Injection (Get-RemoteScriptPath $path)))" -} - -$newCommand.SelectSingleNode("./ua:CommandLine", $namespace).InnerText = ` - "powershell -Command " + ` - "`$env:INSTALLER_SCRIPT = $(Get-ScriptPathInjection $env:SETUP_SCRIPT_NAME);" + ` - "`$env:CONFIG_MODULE = $(Get-ScriptPathInjection $env:CONFIG_MODULE);" + ` - "Invoke-Expression $(Get-ScriptPathInjection "$PSScriptRoot/InitialBoot.ps1");"; - -$orderElement = $newCommand.SelectSingleNode("./ua:Order", $namespace); -$orderElement.InnerText = ([int]($orderElement.InnerText) + 1); -$newCommand.SelectSingleNode("./ua:Description", $namespace).InnerText = "Install PowerShell Core and git and run setup script"; - -if (Get-Command Initialize-SetupConfig -ErrorAction SilentlyContinue) { - Initialize-SetupConfig $unattendedConfig $namespace; -} - -$unattendedConfigFile = "X:\unattend.xml"; -$unattendedConfig.PreserveWhitespace = $true; -$unattendedConfig.Save($unattendedConfigFile); - -Write-Warning "Attention: This program will completely wipe your current disk #1 and install Windows on it. Are you sure you want to do this?" -Read-Host -Prompt "Hit enter to continue or CTRL+C to abort" -& "$SETUP_DRIVE\setup.exe" /Unattend:$unattendedConfigFile; +Start-Setup