#!/bin/pwsh using namespace System.Security.Principal; . "$PSScriptRoot/../../../scripts/Windows/Scripts/Prerequisites.ps1"; . "$PSScriptRoot/../../../scripts/Windows/Scripts/WSL.ps1"; . "$PSScriptRoot/../../Common/Scripts/Context.ps1"; . "$PSScriptRoot/../Scripts/Security.ps1"; . "$PSScriptRoot/../Software/Firefox/Install.ps1"; . "$PSScriptRoot/Manage.ps1"; . "$PSScriptRoot/User/Install.ps1"; $null = New-Module { . "$PSScriptRoot/../Scripts/Deployment.ps1"; . "$PSScriptRoot/../Scripts/Hooks.ps1"; . "$PSScriptRoot/../Scripts/PowerManagement.ps1"; . "$PSScriptRoot/../Scripts/Registry.ps1"; . "$PSScriptRoot/../Scripts/Security.ps1"; . "$PSScriptRoot/../Scripts/Update.ps1"; . "$PSScriptRoot/../Scripts/Users.ps1"; . "$PSScriptRoot/../../Common/Scripts/Config.ps1"; . "$PSScriptRoot/../../Common/Scripts/Operations.ps1"; . "$PSScriptRoot/../../Common/Scripts/Software.ps1"; . "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1"; . "$PSScriptRoot/../../Common/Types/InstallerAction.ps1"; <# .SYNOPSIS Finishes the installation of a running Windows machine. #> function Start-WindowsInstallation { Start-Operation -NoImplicitCleanup { Start-InstallationLoop; }; } <# .SYNOPSIS Starts the installation loop. #> function Start-InstallationLoop { while (-not (Get-IsFinished)) { if (Test-Admin) { $null = Import-Module PSWindowsUpdate; Invoke-Hook "Invoke-WindowsUpdate" -Fallback { Update-WindowsInstallation; }; if ((Get-WURebootStatus -Silent)) { Restart-Intermediate; return; } } switch (Get-Stage) { ($null) { Set-Stage ([SetupStage]::Configure); break; } ([SetupStage]::Configure) { if (Get-Config "valhalla.windows.dualboot.enable") { if (-not (Test-Qemu)) { # Fix synchronization between Linux and Windows clocks. Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" -Name "RealTimeIsUniversal" -Value 1 -Type "DWord"; } # Force time resynchronization $timeZoneOption = "Start"; $timeZoneKey = "HKLM:\SYSTEM\CurrentControlSet\Services\tzautoupdate"; $service = Get-Service W32Time; $autoUpdate = (Get-Item $timeZoneKey).GetValue($timeZoneOption); $stopped = ($service.Status -eq "Stopped"); $setUpdate = { param([int] $Value) Set-ItemProperty $timeZoneKey -Name $timeZoneOption $Value }; & $setUpdate 3; Start-Service $service; w32tm /resync /force; & $setUpdate $autoUpdate; if ($stopped) { Stop-Service $service; } } Set-Stage ([SetupStage]::Install); } ([SetupStage]::Install) { Write-Host "Entering install phase"; Deploy-SoftwareAction; Set-Stage ([SetupStage]::CreateUser); } ([SetupStage]::CreateUser) { $users = @(Get-Users); $i = Get-CurrentUser; for (; $i -lt $users.Count; $i++) { $name = $users[$i]; $msAccount = Get-UserConfig -UserName $name "microsoftAccount"; Set-CurrentUser $i; if (Test-Admin) { Disable-BootMessage; } while ((Get-UserStage) -ne ([UserStage]::Completed)) { switch (Get-UserStage) { ($null) { Set-UserStage ([UserStage]::Create); continue; } ([UserStage]::Create) { if ($env:UserName -ne $name) { $userInfo = @{ name = $name; msAccount = $msAccount; }; New-ValhallaUser @userInfo; if ($msAccount) { logoff; } else { Restart-Intermediate; } exit; } else { if ($msAccount) { if (-not (Test-Admin)) { Invoke-OneShot DisableUAC; Restart-Intermediate -NoRegister; return; } Clear-SetupRegistration; Disable-OneShotListener; } Set-UserStage ([UserStage]::Configure); } } (([UserStage]::Configure)) { $displayName = Get-UserConfig -UserName $name "displayName"; $userArguments = @{ name = $name; }; if ($displayName) { $userArguments.fullName = $displayName; } $adminGroup = @{ SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null); }; Set-LocalUser @userArguments; Deploy-SoftwareAction -Action ([InstallerAction]::ConfigureUser); Remove-LocalGroupMember -Member "$name" @adminGroup -ErrorAction SilentlyContinue; foreach ($group in Get-UserConfig -UserName "$name" "groups") { Add-LocalGroupMember -Member "$name" -Name "$group"; } if (-not $msAccount) { net user $name /logonpasswordchg:yes; } Set-UserStage ([UserStage]::Cleanup); } ([UserStage]::Cleanup) { $user = Get-SetupUser; Disable-LocalUser $name; Enable-LocalUser $user; Set-AutologinUser $user; Unregister-WslDistribution; Set-UserStage ([UserStage]::Completed); Restart-Intermediate; exit; } } } } foreach ($user in $users) { Enable-LocalUser $user; } Set-IsFinished $true; } } } } function Invoke-WindowsInstallation([Context] $context) { $Global:InformationPreference = "Continue"; $Global:ErrorActionPreference = "Inquire"; $context.UserNames ??= @("Manuel"); Start-OldWindowsInstallationScript $context; } function Start-OldWindowsInstallationScript([Context] $context) { . "$PSScriptRoot/Upgrade.ps1"; $finished = $false; Remove-Item Env:\POSH_THEME -ErrorAction SilentlyContinue; $configPath = "$PSScriptRoot/../Config"; $softwarePath = "$PSScriptRoot/../Software"; $initialConfigStage = "InitialConfiguration"; $prerequisitesStage = "InstallationPrerequisites"; $driverStage = "DriverInstallation"; $softwareStage = "MachineWideSoftwareInstallation"; $userStage = "CreatingUser"; $restorationStage = "Restoring"; while (-not $finished) { switch ($context.GetStage()) { { (-not $_) -or ($_ -eq $initialConfigStage) } { $context.SetStage($initialConfigStage); if ((Get-Command Initialize-Configuration -ErrorAction SilentlyContinue)) { Write-Information "Configuration initialization function was found. Running..."; Initialize-Configuration $context; } $null = Enable-WindowsOptionalFeature -Online -All -FeatureName "NetFx3"; . "$configPath/Windows/Install.ps1" $context; . "$configPath/Explorer/Install.ps1" $context; . "$configPath/OpenSSH/Install.ps1" $context; . "$configPath/chocolatey/Install.ps1"; $context.RemoveDesktopIcon("*Microsoft Edge*"); $context.SetStage($prerequisitesStage); break; } # Always install updates default { Write-Host "Starting Installation and Restoration of Windows"; Update-WindowsInstallation $context; } $prerequisitesStage { Write-Host "Installing prerequisites for installing software"; if (-not $(Get-Command winget)) { choco install -y winget; } Install-Module -AcceptLicense -Force "NuGet"; Import-Module NuGet; Install-Firefox $context; choco install -y selenium-gecko-driver; $null = Install-Package -Force Selenium.WebDriver -RequiredVersion 4.10.0 -SkipDependencies; winget install --accept-source-agreements --accept-package-agreements -e --id AutoHotkey.AutoHotkey; $context.SetStage($driverStage); break; } $driverStage { Write-Host "Installing drivers"; if ((Get-Command Install-PortValhallaDrivers -ErrorAction SilentlyContinue)) { Write-Information "Driver installation function was found. Starting installation"; Install-PortValhallaDrivers $context; } Write-Information "Finished installing drivers"; $context.SetStage($softwareStage); $context.Reboot(); exit; } $softwareStage { Write-Host "Setting up software with default app associations"; . "$softwarePath/WinSCP/Install.ps1" $context; . "$softwarePath/Thunderbird/Install.ps1" $context; Write-Host "Installing default settings for new users"; . "$softwarePath/aliae/Install.ps1" $context; . "$softwarePath/posh-git/Install.ps1"; . "$softwarePath/Terminal-Icons/Install.ps1"; . "$softwarePath/Oh My Posh/Install.ps1" $context; $context.SetStage($userStage); break; } $userStage { Install-PersonalUsers $context; $context.SetStage($restorationStage); break; } $restorationStage { Restore-WindowsInstallation $context; $finished = $true; break; } } } } };