windows-oobe-scripts/unattend/desktop-PROMPT-DISK.xml

335 lines
16 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!--
============================================================================
autounattend.xml - Windows 10 Enterprise LTSC 2021 (21H2), x64
Target: Physical desktops/laptops AND virtual machines, UEFI or BIOS
Storage: Any. VirtIO drivers load automatically if a virtio-win ISO is
attached; otherwise use "Load driver" on the disk screen.
Behavior: STOPS at "Where do you want to install Windows?" so you pick
(and delete/format) partitions yourself - nothing is wiped
without you. Then installs, autologons ONCE, installs VirtIO
guest tools if a virtio-win disc is present, and downloads and
runs oobe-desktop.ps1 from https://url.isworking.fyi/oobe-desktop.
BUILD: ./build-isos.sh produces build/desktop.iso with this file as
autounattend.xml plus oobe-desktop.ps1 (offline fallback).
VM: attach it as a second CD next to the LTSC ISO.
PC: copy autounattend.xml and oobe-desktop.ps1 to the root of
the LTSC install USB (or a second USB stick).
Credentials baked in below: silviodante / mdwelcome (stored in CLEAR TEXT)
Search for "EDIT" to find every value you probably want to change.
============================================================================
-->
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<!-- =======================================================================
PASS 1: windowsPE
======================================================================= -->
<settings pass="windowsPE">
<component name="Microsoft-Windows-International-Core-WinPE"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<SetupUILanguage>
<UILanguage>en-US</UILanguage>
</SetupUILanguage>
<InputLocale>0409:00000409</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<!-- ===============================================================
VIRTIO DRIVER INJECTION - the load-bearing part.
WinPE has no viostor/vioscsi driver, so without this the vdisk is
invisible on the disk screen. On physical PCs these paths don't
exist and are skipped; the disk screen's Load Driver button is
still available for anything else (RAID/VMD/NVMe controllers).
Drive letters in WinPE are not deterministic: the LTSC disc and the
VirtIO disc land on D:/E: in either order, so both are listed, plus
F: as insurance. Setup logs a warning for paths that don't exist
and continues, so the extra entries cost nothing.
viostor = VirtIO block bus (Unraid vdisk bus: virtio)
vioscsi = VirtIO SCSI bus (Unraid vdisk bus: virtio-scsi)
NetKVM = network, so WinPE has connectivity if you ever need it
=============================================================== -->
<component name="Microsoft-Windows-PnpCustomizationsWinPE"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<DriverPaths>
<PathAndCredentials wcm:action="add" wcm:keyValue="1">
<Path>D:\viostor\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="2">
<Path>E:\viostor\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="3">
<Path>F:\viostor\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="4">
<Path>D:\vioscsi\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="5">
<Path>E:\vioscsi\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="6">
<Path>F:\vioscsi\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="7">
<Path>D:\NetKVM\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="8">
<Path>E:\NetKVM\w10\amd64</Path>
</PathAndCredentials>
<PathAndCredentials wcm:action="add" wcm:keyValue="9">
<Path>F:\NetKVM\w10\amd64</Path>
</PathAndCredentials>
</DriverPaths>
</component>
<component name="Microsoft-Windows-Setup"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<!-- No DiskConfiguration and no InstallTo on purpose: Setup prompts
for the target disk/partition, which is the only screen shown. -->
<ImageInstall>
<OSImage>
<InstallFrom>
<MetaData wcm:action="add">
<Key>/IMAGE/INDEX</Key>
<Value>1</Value>
</MetaData>
</InstallFrom>
<WillShowUI>OnError</WillShowUI>
</OSImage>
</ImageInstall>
<UserData>
<!-- EDIT: generic KMS client key for Enterprise LTSC 2021. Gets Setup
past the prompt; does NOT activate. N edition is
92NFX-8DJQP-P6BBQ-THF9C-7CG2H. -->
<ProductKey>
<Key>M7XTQ-FN8P6-TTKYV-9D4CC-J462D</Key>
<WillShowUI>OnError</WillShowUI>
</ProductKey>
<AcceptEula>true</AcceptEula>
<FullName>Silvio Dante</FullName>
<Organization>Bada Bing!</Organization>
</UserData>
</component>
</settings>
<!-- =======================================================================
PASS 2: specialize
======================================================================= -->
<settings pass="specialize">
<!-- Runs as SYSTEM before anyone logs on. Lets admins elevate without a
UAC prompt (oobe-*.ps1 sets the same value later), so nothing at
first logon can stall on an elevation prompt nobody is there to
click: the VirtIO installer, or the RunAs launch in step 4. -->
<component name="Microsoft-Windows-Deployment"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Description>Elevate admins without a UAC prompt</Description>
<Path>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v ConsentPromptBehaviorAdmin /t REG_DWORD /d 0 /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
<component name="Microsoft-Windows-Shell-Setup"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<!-- "*" = random name. A literal name must NOT match any local account. -->
<ComputerName>*</ComputerName>
<!-- EDIT: `tzutil /l` lists every valid value. -->
<TimeZone>Pacific Standard Time</TimeZone>
<RegisteredOwner>Silvio Dante</RegisteredOwner>
<RegisteredOrganization>Bada Bing!</RegisteredOrganization>
</component>
<component name="Microsoft-Windows-Security-SPP-UX"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<SkipAutoActivation>true</SkipAutoActivation>
</component>
<!-- RDP on (NLA required) so the machine is reachable remotely. -->
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<fDenyTSConnections>false</fDenyTSConnections>
</component>
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<UserAuthentication>1</UserAuthentication>
<SecurityLayer>2</SecurityLayer>
</component>
</settings>
<!-- =======================================================================
PASS 3: oobeSystem
======================================================================= -->
<settings pass="oobeSystem">
<component name="Microsoft-Windows-International-Core"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<InputLocale>0409:00000409</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<component name="Microsoft-Windows-Shell-Setup"
processorArchitecture="amd64"
publicKeyToken="31bf3856ad364e35"
language="neutral"
versionScope="nonSxS"
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<OOBE>
<HideEULAPage>true</HideEULAPage>
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
<HideLocalAccountScreen>true</HideLocalAccountScreen>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<NetworkLocation>Work</NetworkLocation>
<ProtectYourPC>3</ProtectYourPC>
</OOBE>
<!-- ===============================================================
ACCOUNTS - password is mdwelcome, in clear text, three times.
Treat this file and the merged ISO as secrets.
=============================================================== -->
<UserAccounts>
<AdministratorPassword>
<Value>mdwelcome</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
<LocalAccounts>
<LocalAccount wcm:action="add">
<Name>silviodante</Name>
<DisplayName>Silvio Dante</DisplayName>
<Description>Local administrator for automated builds</Description>
<Group>Administrators</Group>
<Password>
<Value>mdwelcome</Value>
<PlainText>true</PlainText>
</Password>
</LocalAccount>
</LocalAccounts>
</UserAccounts>
<!-- Autologon ONCE, just long enough for the FirstLogonCommands. After
oobe-desktop.ps1 restarts the PC it lands on the sign-in screen. -->
<AutoLogon>
<Enabled>true</Enabled>
<Username>silviodante</Username>
<LogonCount>1</LogonCount>
<Password>
<Value>mdwelcome</Value>
<PlainText>true</PlainText>
</Password>
</AutoLogon>
<DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet>
<!-- ===============================================================
FIRST LOGON COMMANDS - run once, elevated, as silviodante.
=============================================================== -->
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<Description>Show file extensions</Description>
<CommandLine>reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
<SynchronousCommand wcm:action="add">
<Order>2</Order>
<Description>Allow signed PowerShell scripts</Description>
<CommandLine>powershell -NoProfile -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force"</CommandLine>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
<!-- VMs only: if a virtio-win disc is attached, install the guest
tools (NetKVM is needed before anything can be downloaded). On
physical PCs no drive has the installer and this does nothing. Scans every drive for
the installer rather than assuming a letter, since the VirtIO
disc moves around post-install. Waits at most 15 minutes, so a stuck
installer can never block the next step. -->
<SynchronousCommand wcm:action="add">
<Order>3</Order>
<Description>Install VirtIO guest tools</Description>
<CommandLine>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) } }"</CommandLine>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
<!-- Provisioning: pulls oobe-desktop.ps1 from the repo so the PC always
gets the current version, retrying for ~2.5 minutes while the
network comes up. If that fails, falls back to the copy of
oobe-desktop.ps1 baked into the root of the ISO. The script is saved to
C:\ProgramData\OOBE and started elevated in its own window,
so this step finishes as soon as it has launched it. The script installs
the MeshCentral agent, applies the power/RDP/SSH settings and
restarts the PC itself, so this must stay the LAST command.
Step log: C:\ProgramData\OOBE\firstlogon.log (download / fallback / launch)
Log: C:\ProgramData\OOBE\oobe-desktop.log -->
<SynchronousCommand wcm:action="add">
<Order>4</Order>
<Description>Run oobe-desktop.ps1 (url.isworking.fyi, else ISO copy)</Description>
<CommandLine>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 }"</CommandLine>
<RequiresUserInput>false</RequiresUserInput>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>
</unattend>