Files
cloudhost/seediso/windows11/Configure-Windows.ps1
T
GuofangandClaude Sonnet 5.5 1ac9221198 Copy the installer batch files to an Installers folder on the desktop
Adds a -CopyInstallers switch to the Windows 11 configure script and enables
it in Autounattend.xml.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 13:58:41 +08:00

197 lines
6.9 KiB
PowerShell

param(
[switch]$InstallVirtIO,
[switch]$EnableAutomaticLogon,
[switch]$DisableAutoUpdate,
[switch]$CopyInstallers,
[switch]$NoPause
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
function Test-Administrator {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
if (-not (Test-Administrator)) {
if (-not $PSCommandPath) {
throw 'Run this script from a PowerShell window opened as Administrator.'
}
$arguments = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', "`"$PSCommandPath`"")
foreach ($name in $PSBoundParameters.Keys) {
$arguments += "-$name"
}
$elevated = Start-Process `
-FilePath 'powershell.exe' `
-ArgumentList $arguments `
-Verb RunAs `
-Wait `
-PassThru
exit $elevated.ExitCode
}
function Install-VirtIOGuestTools {
$installer = Get-ChildItem `
-Path (Get-PSDrive -PSProvider FileSystem).Root `
-Filter 'virtio-win-guest-tools.exe' `
-File `
-ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $installer) {
throw 'virtio-win-guest-tools.exe was not found on the attached media.'
}
$process = Start-Process `
-FilePath $installer.FullName `
-ArgumentList '/quiet', '/norestart' `
-Wait `
-PassThru
if ($process.ExitCode -notin 0, 3010) {
throw "VirtIO guest tools installer exited with code $($process.ExitCode)."
}
}
function Install-OpenSSHServer {
$capability = Get-WindowsCapability -Online -Name 'OpenSSH.Server*' |
Select-Object -First 1
if (-not $capability) {
throw 'The OpenSSH Server Windows capability was not found.'
}
if ($capability.State -ne 'Installed') {
Add-WindowsCapability -Online -Name $capability.Name | Out-Null
}
Set-Service -Name 'sshd' -StartupType Automatic
Start-Service -Name 'sshd'
$rule = Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -ErrorAction SilentlyContinue
if ($rule) {
Set-NetFirewallRule `
-Name 'OpenSSH-Server-In-TCP' `
-Enabled True `
-Profile Private, Public
}
else {
New-NetFirewallRule `
-Name 'OpenSSH-Server-In-TCP' `
-DisplayName 'OpenSSH SSH Server (sshd)' `
-Enabled True `
-Direction Inbound `
-Protocol TCP `
-Action Allow `
-LocalPort 22 `
-Profile Private, Public | Out-Null
}
}
function Install-AdministratorAuthorizedKey {
$authorizedKeys = Join-Path $env:ProgramData 'ssh\administrators_authorized_keys'
$publicKey = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCwsF2ZDSHDaXM9BdDq3Vxkp6T+DJEakKaVZQJUEHexS34mbrxYAxmGBUPCrddfE01dS31kGS4XHVBa+wGUYodY+nPwnrfD1Q4phKVSzXr65K1Y/sCcjSiANBPWpv2Xd7IMOfLlrdLtmf5QcKWroIqO2LaIDGECwzUUHrfprgeaF9N0FGcmrgbmm23JUk+f6guRQ4br88L4rWIWEBvL9bTdwErNkdfsYE2F/U8aIFpMcVy2eJIOgy8ZjZvkGdm4r730YkTDL1VmAjiHH3/m2R1EOvwLzFhyWKoa4ULk/IQW+8iNnG42QEcaWRM+hMwlVdnNhPJP6WzS+fAEbibD3zM0q2X/4ex+cXRNOCd2/0KhnD2+3p1BM5QeFTzDappkk8W2meQkDE3hvTjtIQCzygFO6LNWtEEa7BTvvlMqF3CZWh88J9XiP750SjESe3Ge5o9A0T2hcJa+KZ1LxVEmNt4nD6E/OD4EymoaLIJZ1fH5ksSFjHzJ+mJouSVjc/H/VSE= guofang@GUOFANG-OFFICE'
[IO.File]::WriteAllText(
$authorizedKeys,
$publicKey + [Environment]::NewLine,
[Text.Encoding]::ASCII
)
& icacls.exe `
$authorizedKeys `
'/inheritance:r' `
'/grant' `
'*S-1-5-32-544:F' `
'*S-1-5-18:F'
if ($LASTEXITCODE -ne 0) {
throw "icacls.exe exited with code $LASTEXITCODE."
}
}
function Enable-AutomaticLogon {
$winlogonPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
Set-ItemProperty -Path $winlogonPath -Name 'AutoAdminLogon' -Value '1' -Type String
Set-ItemProperty -Path $winlogonPath -Name 'DefaultUserName' -Value 'guofang' -Type String
Set-ItemProperty -Path $winlogonPath -Name 'DefaultPassword' -Value 'wang' -Type String
Set-ItemProperty -Path $winlogonPath -Name 'DefaultDomainName' -Value $env:COMPUTERNAME -Type String
Remove-ItemProperty -Path $winlogonPath -Name 'AutoLogonCount' -ErrorAction SilentlyContinue
}
function Disable-AutomaticUpdate {
$windowsUpdatePath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate'
$autoUpdatePath = Join-Path $windowsUpdatePath 'AU'
$storePath = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsStore'
$currentVersion = Get-ItemProperty `
-Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
$releaseVersion = $currentVersion.DisplayVersion
New-Item -Path $autoUpdatePath -Force | Out-Null
New-Item -Path $storePath -Force | Out-Null
# Never check automatically; manual checks and installs keep working.
Set-ItemProperty -Path $autoUpdatePath -Name 'NoAutoUpdate' -Value 1 -Type DWord
Set-ItemProperty -Path $autoUpdatePath -Name 'NoAutoRebootWithLoggedOnUsers' -Value 1 -Type DWord
Set-ItemProperty -Path $windowsUpdatePath -Name 'ExcludeWUDriversInQualityUpdate' -Value 1 -Type DWord
# Stay on the installed feature release instead of upgrading automatically.
if ($releaseVersion) {
Set-ItemProperty -Path $windowsUpdatePath -Name 'TargetReleaseVersion' -Value 1 -Type DWord
Set-ItemProperty -Path $windowsUpdatePath -Name 'TargetReleaseVersionInfo' -Value $releaseVersion -Type String
}
# 2 = never download Microsoft Store app updates automatically.
Set-ItemProperty -Path $storePath -Name 'AutoDownload' -Value 2 -Type DWord
# Windows may re-enable this task, so the policies above are the real switch.
Disable-ScheduledTask `
-TaskPath '\Microsoft\Windows\UpdateOrchestrator\' `
-TaskName 'Schedule Scan' `
-ErrorAction SilentlyContinue | Out-Null
}
function Copy-InstallerScripts {
$scripts = @(Get-ChildItem -Path $PSScriptRoot -Filter '*-Install-*.bat' -File)
if ($scripts.Count -eq 0) {
throw "No installer batch files were found next to $PSCommandPath."
}
$target = Join-Path ([Environment]::GetFolderPath('Desktop')) 'Installers'
New-Item -ItemType Directory -Path $target -Force | Out-Null
Copy-Item -Path $scripts.FullName -Destination $target -Force
}
$exitCode = 0
try {
if ($InstallVirtIO) {
Install-VirtIOGuestTools
}
Install-OpenSSHServer
Install-AdministratorAuthorizedKey
if ($EnableAutomaticLogon) {
Enable-AutomaticLogon
}
if ($DisableAutoUpdate) {
Disable-AutomaticUpdate
}
if ($CopyInstallers) {
Copy-InstallerScripts
}
Write-Host 'Done.' -ForegroundColor Green
}
catch {
Write-Host "Failed: $($_.Exception.Message)" -ForegroundColor Red
$exitCode = 1
}
if (-not $NoPause) {
Read-Host 'Press Enter to exit' | Out-Null
}
exit $exitCode