<# .SYNOPSIS Installs all available Windows Updates via PSWindowsUpdate module. .DESCRIPTION First pass: installs all currently available updates without rebooting. Then registers a scheduled task "X9-WindowsUpdate" that runs on every logon (as SYSTEM) until no more updates are found - handles the typical 2-3 reboot cycles required on a fresh Windows installation. Operator workflow: 1. xetup completes all steps 2. Operator reboots manually 3. On each subsequent logon the scheduled task runs another update pass 4. Task removes itself automatically when system is fully up to date .ITEMS nainstalovat-pswindowsupdate-modul: Installs NuGet provider and PSWindowsUpdate module from PSGallery. spustit-prvni-kolo-windows-update: First update pass without reboot - installs all currently available updates. registrovat-scheduled-task-pro-dalsi-kola: Registers X9-WindowsUpdate scheduled task that runs on logon, handles post-reboot update rounds, and self-deletes when no more updates are found. #> param( [object]$Config, [string]$LogFile ) $ErrorActionPreference = "Continue" function Write-Log { param([string]$Message, [string]$Level = "INFO") $line = "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message" $null = New-Item -ItemType Directory -Force -Path (Split-Path $LogFile -Parent) -ErrorAction SilentlyContinue Add-Content -Path $LogFile -Value $line -Encoding UTF8 Write-Output $line } Write-Log "=== Step 12 - Windows Update ===" -Level STEP # ----------------------------------------------------------------------- # 1. NuGet provider + PSWindowsUpdate module # ----------------------------------------------------------------------- Write-Log "Setting up PSWindowsUpdate module..." -Level INFO try { Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope AllUsers | Out-Null $existing = Get-Module -ListAvailable -Name PSWindowsUpdate | Select-Object -First 1 if ($existing) { Write-Log " PSWindowsUpdate $($existing.Version) already installed" -Level INFO } else { Install-Module -Name PSWindowsUpdate -Force -Scope AllUsers -AllowClobber | Out-Null Write-Log " PSWindowsUpdate installed" -Level OK } Import-Module PSWindowsUpdate -Force } catch { Write-Log " Module setup failed: $_" -Level ERROR exit 1 } # ----------------------------------------------------------------------- # 2. First update pass (no reboot) # ----------------------------------------------------------------------- Write-Log "Running first Windows Update pass..." -Level INFO try { $result = Install-WindowsUpdate -AcceptAll -IgnoreReboot -Verbose 2>&1 $installed = @($result | Where-Object { $_ -match 'KB\d+|Downloaded|Installed' }) if ($installed.Count -gt 0) { $result | Where-Object { "$_" -match '\S' } | ForEach-Object { Write-Log " $_" -Level INFO } Write-Log " First pass complete - reboot required for remaining rounds" -Level OK } else { Write-Log " System already up to date" -Level OK } } catch { Write-Log " First pass failed: $_" -Level ERROR } # ----------------------------------------------------------------------- # 3. Enable autologon for adminx9 (temporary - disabled when updates complete) # ----------------------------------------------------------------------- Write-Log "Enabling temporary autologon for adminx9..." -Level INFO $winlogonPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" try { Set-ItemProperty -Path $winlogonPath -Name "AutoAdminLogon" -Value "1" -Type String -Force Set-ItemProperty -Path $winlogonPath -Name "DefaultUserName" -Value "adminx9" -Type String -Force Set-ItemProperty -Path $winlogonPath -Name "DefaultPassword" -Value "" -Type String -Force Set-ItemProperty -Path $winlogonPath -Name "DefaultDomainName" -Value "." -Type String -Force # Safety cap: max 10 automatic logons in case the task fails to clean up Set-ItemProperty -Path $winlogonPath -Name "AutoLogonCount" -Value 10 -Type DWord -Force Write-Log " Autologon enabled (adminx9, max 10 rounds)" -Level OK } catch { Write-Log " Failed to enable autologon: $_" -Level WARN Write-Log " Windows Update rounds will require manual login after each reboot" -Level WARN } # ----------------------------------------------------------------------- # 4. Scheduled task for post-reboot update rounds (self-deleting) # ----------------------------------------------------------------------- Write-Log "Registering post-reboot update task..." -Level INFO $taskName = "X9-WindowsUpdate" # PowerShell block that runs on each logon until no more updates found. # When done: disables autologon and removes itself. $updateScript = @' Import-Module PSWindowsUpdate -Force -ErrorAction Stop $updates = Get-WindowsUpdate -AcceptAll -IgnoreReboot if ($updates) { Install-WindowsUpdate -AcceptAll -IgnoreReboot | Out-File "C:\Windows\Setup\Scripts\wu-pass-$(Get-Date -Format 'yyyyMMdd-HHmmss').log" -Encoding UTF8 } else { # No more updates - disable autologon and remove this task $wl = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" Set-ItemProperty -Path $wl -Name "AutoAdminLogon" -Value "0" -Type String -Force Remove-ItemProperty -Path $wl -Name "DefaultPassword" -ErrorAction SilentlyContinue Remove-ItemProperty -Path $wl -Name "AutoLogonCount" -ErrorAction SilentlyContinue Unregister-ScheduledTask -TaskName "X9-WindowsUpdate" -Confirm:$false } '@ try { $action = New-ScheduledTaskAction -Execute "powershell.exe" ` -Argument "-NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -Command `"$updateScript`"" $trigger = New-ScheduledTaskTrigger -AtLogOn $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Hours 2) ` -MultipleInstances IgnoreNew $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest # Remove existing task first (idempotent) Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger ` -Settings $settings -Principal $principal -Force | Out-Null Write-Log " Task '$taskName' registered - runs on each logon until fully updated" -Level OK } catch { Write-Log " Failed to register scheduled task: $_" -Level WARN Write-Log " Manual Windows Update rounds will be needed after reboot" -Level WARN } Write-Log "Step 12 - Windows Update complete" -Level OK