Private/New-Win32ToolkitUnattendXml.ps1

function New-Win32ToolkitUnattendXml {
    <#
    .SYNOPSIS
        Builds the unattend.xml that makes an offline-applied Windows 11 image first-boot fully
        unattended (local admin + autologon + full OOBE skip + PS-Direct readiness).
    .DESCRIPTION
        Data-driven generator for the golden-image answer file. Machine settings go in the `specialize`
        pass; account / OOBE-skip / AutoLogon go in `oobeSystem` (windowsPE does NOT run for an
        offline-applied VHDX). The Windows 11 mandatory-MSA/network gate is skipped by the documented
        combination HideOnlineAccountScreens + a pre-created LocalAccount + AutoLogon (NOT the unreliable
        SkipMachineOOBE). All caller-supplied values are XML-encoded (ConvertTo-XmlEncoded), and the
        account name is reduced to its SAM part (a leading '.\' or 'COMPUTER\' is stripped).
 
        SECURITY: PlainText=true stores the password in cleartext inside the VHDX and it persists under
        %WINDIR%\Panther — the built base VHDX must be treated as a secret. See
        knowledge-base/designs/hyperv-golden-image-build.md (§2.3).
    .PARAMETER AdminCredential
        The local-admin account to create + auto-logon (the same credential PowerShell Direct will use).
    .PARAMETER ComputerName
        Guest computer name (specialize pass). Default 'GOLDENBASE'.
    .PARAMETER Locale
        BCP-47 locale for InputLocale/SystemLocale/UILanguage/UserLocale. Default 'en-US'.
    .PARAMETER LogonCount
        AutoLogon count. Windows adds 1 when >0, so a single auto-logon isn't achievable — the checkpoint
        freezes the post-first-boot state anyway. Default 999.
    .OUTPUTS
        [string] the unattend.xml document.
    #>

    [CmdletBinding()]
    [OutputType([string])]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNull()]
        [pscredential]$AdminCredential,

        [ValidateNotNullOrEmpty()]
        [string]$ComputerName = 'GOLDENBASE',

        [ValidateNotNullOrEmpty()]
        [string]$Locale = 'en-US',

        [ValidateRange(1, 999)]
        [int]$LogonCount = 999
    )

    # SAM account name only — strip a leading '.\' or 'DOMAIN\' so AutoLogon/LocalAccount get 'w32admin'.
    $sam     = $AdminCredential.UserName.Split('\')[-1]
    $user    = ConvertTo-XmlEncoded $sam
    $pwPlain = [System.Net.NetworkCredential]::new('', $AdminCredential.Password).Password
    if ([string]::IsNullOrEmpty($pwPlain)) {
        throw 'AdminCredential password must not be empty — a blank password breaks AutoLogon and PowerShell Direct on the guest.'
    }
    $pw      = ConvertTo-XmlEncoded $pwPlain
    $cn      = ConvertTo-XmlEncoded $ComputerName
    $loc     = ConvertTo-XmlEncoded $Locale

    @"
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
  <settings pass="specialize">
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <ComputerName>$cn</ComputerName>
      <TimeZone>UTC</TimeZone>
    </component>
    <!-- Win11 24H2/25H2 ASSIST (not the load-bearing mechanism): if OOBE presents the mandatory
         "connect to a network" gate before the oobeSystem LocalAccount/AutoLogon pass is reached, this
         offline-path flag lets it through. specialize runs before the OOBE pass, so it is set in time.
         UNSUPPORTED / undocumented — Microsoft may reset it on newer builds; revalidate per 25H2 build.
         The load-bearing skip is the pre-created LocalAccount + AutoLogon + a NON-BLANK password. -->
    <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <RunSynchronous>
        <RunSynchronousCommand wcm:action="add">
          <Order>1</Order>
          <Path>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE /v BypassNRO /t REG_DWORD /d 1 /f</Path>
          <Description>Enable offline OOBE path (bypass network requirement)</Description>
        </RunSynchronousCommand>
        <RunSynchronousCommand wcm:action="add">
          <Order>2</Order>
          <Path>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f</Path>
          <Description>Give remote / PowerShell Direct local admins a FULL (elevated) token so HKLM writes and elevated tasks do not silently fail at medium integrity</Description>
        </RunSynchronousCommand>
      </RunSynchronous>
    </component>
  </settings>
  <settings pass="oobeSystem">
    <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <InputLocale>$loc</InputLocale>
      <SystemLocale>$loc</SystemLocale>
      <UILanguage>$loc</UILanguage>
      <UserLocale>$loc</UserLocale>
    </component>
    <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
        <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
        <NetworkLocation>Work</NetworkLocation>
        <ProtectYourPC>3</ProtectYourPC>
      </OOBE>
      <UserAccounts>
        <LocalAccounts>
          <LocalAccount wcm:action="add">
            <Name>$user</Name>
            <Group>Administrators</Group>
            <DisplayName>$user</DisplayName>
            <Password><Value>$pw</Value><PlainText>true</PlainText></Password>
          </LocalAccount>
        </LocalAccounts>
      </UserAccounts>
      <AutoLogon>
        <Username>$user</Username>
        <Enabled>true</Enabled>
        <LogonCount>$LogonCount</LogonCount>
        <Password><Value>$pw</Value><PlainText>true</PlainText></Password>
      </AutoLogon>
      <FirstLogonCommands>
        <SynchronousCommand wcm:action="add">
          <Order>1</Order>
          <CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned -Force"</CommandLine>
          <Description>Prep Windows PowerShell 5.1 for device scripts (also enforced host-side before checkpoint)</Description>
        </SynchronousCommand>
      </FirstLogonCommands>
    </component>
  </settings>
</unattend>
"@

}