diff --git a/oobe-desktop.ps1 b/oobe-desktop.ps1 index 9d76589..d8dcd39 100644 --- a/oobe-desktop.ps1 +++ b/oobe-desktop.ps1 @@ -3,12 +3,6 @@ # irm https://url.isworking.fyi/oobe-desktop | iex # Log: C:\ProgramData\OOBE\oobe-desktop.log -# Check if running with elevated privileges -if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { - Write-Host "Please run this script as an administrator." - Exit 1 -} - $MeshAgentUrl = "https://rmm.iamchrisama.com/meshagents?id=4&meshid=zxl@U2zM95zh9ZNqah@9mUEjCJ3ptGOE6s5cjsGniacVU1fjRXtVKCKlKJN4aJQW&installflags=0" $ErrorActionPreference = 'Continue' @@ -21,6 +15,13 @@ $WorkDir = Join-Path $env:ProgramData 'OOBE' New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null Start-Transcript -Path (Join-Path $WorkDir 'oobe-desktop.log') -Append | Out-Null +# Check if running with elevated privileges (after the transcript starts, so this still leaves a log) +if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + Write-Warning "Not running as administrator, stopping. Rerun from an elevated PowerShell." + Stop-Transcript | Out-Null + Exit 1 +} + function Save-Download($Uri, $OutFile) { for ($Attempt = 1; $Attempt -le 3; $Attempt++) { try { @@ -110,7 +111,10 @@ if (Get-Service -Name 'Mesh Agent' -ErrorAction SilentlyContinue) { $MeshInstaller = Join-Path $WorkDir 'meshagent.exe' if (Save-Download $MeshAgentUrl $MeshInstaller) { # -fullinstall installs and starts the service without showing the install dialog - Start-Process -FilePath $MeshInstaller -ArgumentList '-fullinstall' -WindowStyle Hidden -Wait + $Process = Start-Process -FilePath $MeshInstaller -ArgumentList '-fullinstall' -WindowStyle Hidden -PassThru + if (-not $Process.WaitForExit(300000)) { + Write-Warning "Mesh Agent installer still running after 5 minutes, continuing." + } } if (-not (Get-Service -Name 'Mesh Agent' -ErrorAction SilentlyContinue)) { Write-Warning "Mesh Agent service was not found after install." @@ -140,10 +144,17 @@ if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyCon } # Install Winget (LTSC ships without the Store / App Installer) -# Run in a child process: the installer script calls exit, which would end this script too +# Run in a child process (the installer script calls exit, which would end this script too), +# with a time limit so it can't hold up the restart. Its output goes to winget-install*.log. $WingetInstaller = Join-Path $WorkDir 'winget-install.ps1' if (Save-Download 'https://github.com/asheroto/winget-install/releases/latest/download/winget-install.ps1' $WingetInstaller) { - & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $WingetInstaller -Force + $Process = Start-Process powershell.exe -ArgumentList '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $WingetInstaller, '-Force' -PassThru ` + -RedirectStandardOutput (Join-Path $WorkDir 'winget-install.log') -RedirectStandardError (Join-Path $WorkDir 'winget-install-errors.log') + if ($Process.WaitForExit(900000)) { + Write-Output "Winget installer exited with code $($Process.ExitCode)" + } else { + Write-Warning "Winget installer still running after 15 minutes, continuing." + } } # Restart to finish OpenSSH and driver installation. diff --git a/oobe-vms.ps1 b/oobe-vms.ps1 index 7d2ca66..a1d275e 100644 --- a/oobe-vms.ps1 +++ b/oobe-vms.ps1 @@ -3,12 +3,6 @@ # irm https://url.isworking.fyi/oobe-vms | iex # Log: C:\ProgramData\OOBE\oobe-vms.log -# Check if running with elevated privileges -if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { - Write-Host "Please run this script as an administrator." - Exit 1 -} - $MeshAgentUrl = "https://rmm.iamchrisama.com/meshagents?id=4&meshid=zxl@U2zM95zh9ZNqah@9mUEjCJ3ptGOE6s5cjsGniacVU1fjRXtVKCKlKJN4aJQW&installflags=0" $ErrorActionPreference = 'Continue' @@ -21,6 +15,13 @@ $WorkDir = Join-Path $env:ProgramData 'OOBE' New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null Start-Transcript -Path (Join-Path $WorkDir 'oobe-vms.log') -Append | Out-Null +# Check if running with elevated privileges (after the transcript starts, so this still leaves a log) +if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + Write-Warning "Not running as administrator, stopping. Rerun from an elevated PowerShell." + Stop-Transcript | Out-Null + Exit 1 +} + function Save-Download($Uri, $OutFile) { for ($Attempt = 1; $Attempt -le 3; $Attempt++) { try { @@ -75,8 +76,14 @@ if (Get-Service -Name 'QEMU-GA' -ErrorAction SilentlyContinue) { ForEach-Object { $Store.Add($_) } $Store.Close() - $Process = Start-Process -FilePath $GuestTools -ArgumentList '/install', '/quiet', '/norestart' -Wait -PassThru - Write-Output "VirtIO guest tools installer exited with code $($Process.ExitCode) (0 = success, 3010 = reboot required)" + # Wait on the installer only, with a time limit: Start-Process -Wait also waits for anything + # the installer leaves running (agents, services), which can block forever + $Process = Start-Process -FilePath $GuestTools -ArgumentList '/install', '/quiet', '/norestart' -PassThru + if ($Process.WaitForExit(900000)) { + Write-Output "VirtIO guest tools installer exited with code $($Process.ExitCode) (0 = success, 3010 = reboot required)" + } else { + Write-Warning "VirtIO guest tools installer still running after 15 minutes, continuing." + } } } @@ -176,7 +183,10 @@ if (Get-Service -Name 'Mesh Agent' -ErrorAction SilentlyContinue) { $MeshInstaller = Join-Path $WorkDir 'meshagent.exe' if (Save-Download $MeshAgentUrl $MeshInstaller) { # -fullinstall installs and starts the service without showing the install dialog - Start-Process -FilePath $MeshInstaller -ArgumentList '-fullinstall' -WindowStyle Hidden -Wait + $Process = Start-Process -FilePath $MeshInstaller -ArgumentList '-fullinstall' -WindowStyle Hidden -PassThru + if (-not $Process.WaitForExit(300000)) { + Write-Warning "Mesh Agent installer still running after 5 minutes, continuing." + } } if (-not (Get-Service -Name 'Mesh Agent' -ErrorAction SilentlyContinue)) { Write-Warning "Mesh Agent service was not found after install." @@ -206,10 +216,17 @@ if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyCon } # Install Winget (LTSC ships without the Store / App Installer) -# Run in a child process: the installer script calls exit, which would end this script too +# Run in a child process (the installer script calls exit, which would end this script too), +# with a time limit so it can't hold up the restart. Its output goes to winget-install*.log. $WingetInstaller = Join-Path $WorkDir 'winget-install.ps1' if (Save-Download 'https://github.com/asheroto/winget-install/releases/latest/download/winget-install.ps1' $WingetInstaller) { - & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $WingetInstaller -Force + $Process = Start-Process powershell.exe -ArgumentList '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $WingetInstaller, '-Force' -PassThru ` + -RedirectStandardOutput (Join-Path $WorkDir 'winget-install.log') -RedirectStandardError (Join-Path $WorkDir 'winget-install-errors.log') + if ($Process.WaitForExit(900000)) { + Write-Output "Winget installer exited with code $($Process.ExitCode)" + } else { + Write-Warning "Winget installer still running after 15 minutes, continuing." + } } # Restart to finish driver, guest tools and OpenSSH installation. diff --git a/unattend/desktop-PROMPT-DISK.xml b/unattend/desktop-PROMPT-DISK.xml index 599ee7a..6c645db 100644 --- a/unattend/desktop-PROMPT-DISK.xml +++ b/unattend/desktop-PROMPT-DISK.xml @@ -141,6 +141,25 @@ ======================================================================= --> + + + + + 1 + Elevate admins without a UAC prompt + reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 0 /f + + + + + disc moves around post-install. Waits at most 15 minutes, so a stuck + installer can never block the next step. --> 3 Install VirtIO guest tools - powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-Volume | Where-Object DriveLetter | ForEach-Object { $exe = $_.DriveLetter + ':\virtio-win-guest-tools.exe'; if (Test-Path $exe) { Start-Process $exe -ArgumentList '/install','/quiet','/norestart' -Wait } }" + powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-Volume | Where-Object DriveLetter | ForEach-Object { $exe = $_.DriveLetter + ':\virtio-win-guest-tools.exe'; if (Test-Path $exe) { $p = Start-Process $exe -ArgumentList '/install','/quiet','/norestart' -PassThru; [void]$p.WaitForExit(900000) } }" false 4 Run oobe-desktop.ps1 (url.isworking.fyi, else ISO copy) - powershell -NoProfile -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $s = $null; for ($i = 1; $i -le 10; $i++) { try { $s = Invoke-RestMethod 'https://url.isworking.fyi/oobe-desktop'; break } catch { Start-Sleep -Seconds 15 } }; if (-not $s) { $f = Get-PSDrive -PSProvider FileSystem | ForEach-Object { Join-Path $_.Root 'oobe-desktop.ps1' } | Where-Object { Test-Path $_ } | Select-Object -First 1; if ($f) { $s = Get-Content -Raw $f } }; if ($s) { Invoke-Expression $s } else { Write-Warning 'oobe-desktop.ps1 not found online or on any drive'; Start-Sleep -Seconds 60 }" + powershell -NoProfile -ExecutionPolicy Bypass -Command "$d = Join-Path $env:ProgramData 'OOBE'; New-Item -ItemType Directory -Force $d | Out-Null; Start-Transcript (Join-Path $d 'firstlogon.log') -Append; [Net.ServicePointManager]::SecurityProtocol = 'Tls12'; $s = $null; for ($i = 1; $i -le 10; $i++) { try { $s = irm 'https://url.isworking.fyi/oobe-desktop' -UseBasicParsing; 'Downloaded'; break } catch { 'Attempt ' + $i + ' failed: ' + $_; sleep 15 } }; if (-not $s) { $f = Get-PSDrive -PSProvider FileSystem | % { Join-Path $_.Root 'oobe-desktop.ps1' } | ? { Test-Path $_ } | select -First 1; if ($f) { 'Using ' + $f; $s = Get-Content -Raw $f } }; if ($s) { $p = Join-Path $d 'oobe-desktop.ps1'; Set-Content $p $s; Start-Process powershell -Verb RunAs -ArgumentList ('-NoProfile -ExecutionPolicy Bypass -File ' + $p); 'Started ' + $p } else { Write-Warning 'oobe-desktop.ps1 not found online or on any drive'; sleep 60 }" false diff --git a/unattend/vms-WIPE-DISK.xml b/unattend/vms-WIPE-DISK.xml index 7c11d1d..3ca9a63 100644 --- a/unattend/vms-WIPE-DISK.xml +++ b/unattend/vms-WIPE-DISK.xml @@ -188,6 +188,25 @@ ======================================================================= --> + + + + + 1 + Elevate admins without a UAC prompt + reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 0 /f + + + + + disc moves around post-install. Waits at most 15 minutes, so a stuck + installer can never block the next step. --> 3 Install VirtIO guest tools - powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-Volume | Where-Object DriveLetter | ForEach-Object { $exe = $_.DriveLetter + ':\virtio-win-guest-tools.exe'; if (Test-Path $exe) { Start-Process $exe -ArgumentList '/install','/quiet','/norestart' -Wait } }" + powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-Volume | Where-Object DriveLetter | ForEach-Object { $exe = $_.DriveLetter + ':\virtio-win-guest-tools.exe'; if (Test-Path $exe) { $p = Start-Process $exe -ArgumentList '/install','/quiet','/norestart' -PassThru; [void]$p.WaitForExit(900000) } }" false 4 Run oobe-vms.ps1 (url.isworking.fyi, else ISO copy) - powershell -NoProfile -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $s = $null; for ($i = 1; $i -le 10; $i++) { try { $s = Invoke-RestMethod 'https://url.isworking.fyi/oobe-vms'; break } catch { Start-Sleep -Seconds 15 } }; if (-not $s) { $f = Get-PSDrive -PSProvider FileSystem | ForEach-Object { Join-Path $_.Root 'oobe-vms.ps1' } | Where-Object { Test-Path $_ } | Select-Object -First 1; if ($f) { $s = Get-Content -Raw $f } }; if ($s) { Invoke-Expression $s } else { Write-Warning 'oobe-vms.ps1 not found online or on any drive'; Start-Sleep -Seconds 60 }" + powershell -NoProfile -ExecutionPolicy Bypass -Command "$d = Join-Path $env:ProgramData 'OOBE'; New-Item -ItemType Directory -Force $d | Out-Null; Start-Transcript (Join-Path $d 'firstlogon.log') -Append; [Net.ServicePointManager]::SecurityProtocol = 'Tls12'; $s = $null; for ($i = 1; $i -le 10; $i++) { try { $s = irm 'https://url.isworking.fyi/oobe-vms' -UseBasicParsing; 'Downloaded'; break } catch { 'Attempt ' + $i + ' failed: ' + $_; sleep 15 } }; if (-not $s) { $f = Get-PSDrive -PSProvider FileSystem | % { Join-Path $_.Root 'oobe-vms.ps1' } | ? { Test-Path $_ } | select -First 1; if ($f) { 'Using ' + $f; $s = Get-Content -Raw $f } }; if ($s) { $p = Join-Path $d 'oobe-vms.ps1'; Set-Content $p $s; Start-Process powershell -Verb RunAs -ArgumentList ('-NoProfile -ExecutionPolicy Bypass -File ' + $p); 'Started ' + $p } else { Write-Warning 'oobe-vms.ps1 not found online or on any drive'; sleep 60 }" false