@@ -1,8 +1,11 @@
# Requires -Version 5.1
# Pure generator: collected values -> Windows Setup answer-file XML string.
# No WinForms dependency (unit-testable). Mirrors the legacy autounattend.xml but with
# ONE real local-admin account (no sm-bootstrap) and an embedded preconfig.json that a
# specialize-pass c ommand writes to C:\ProgramData\SilverMetal\preconfig.json.
# ONE real local-admin account (no sm-bootstrap) and an embedded preconfig.json that the
# oobeSystem FirstLogonC ommands write (in short base64 chunks) to
# C:\ProgramData\SilverMetal\preconfig.json. The base64 is carried in chunked echo
# commands rather than a single specialize RunSynchronousCommand/Path, because that Path
# is capped at ~259 chars and a full base64 blob overflows it -> "answer file is invalid".
function New-SmAnswerFile {
param (
@@ -29,7 +32,45 @@ function New-SmAnswerFile {
function EscContent([string]$s ) { $s . Replace ( '&' , '&' ) . Replace ( '<' , '<' ) . Replace ( '>' , '>' ) }
$dn = Esc $DisplayName ; $un = Esc $Username ; $pw = Esc $Password ; $cn = Esc $ComputerName
$writePre = " powershell -NoProfile -ExecutionPolicy Bypass -Command "" New-Item -ItemType Directory -Force 'C:\ProgramData\SilverMetal' | Out-Null; [IO.File]::WriteAllBytes('C:\ProgramData\SilverMetal\preconfig.json', [Convert]::FromBase64String(' $preB64 ')) "" "
# Build the oobeSystem FirstLogonCommands. The preconfig base64 is split into short
# (<=150 char) chunks, each appended to a temp file by its own `echo` command, then
# the file is whitespace-stripped + base64-decoded into preconfig.json. This keeps
# every single command line well under the unattend length limits.
$preDir = 'C:\ProgramData\SilverMetal'
$preB64File = " $preDir \pre.b64 "
$preFile = " $preDir \preconfig.json "
# Split base64 into chunks of at most 150 chars (base64 alphabet has no XML/cmd
# metachars, so chunks are safe in `echo` and in XML once `>` is escaped).
$chunkSize = 150
$chunks = for ( $i = 0 ; $i -lt $preB64 . Length ; $i + = $chunkSize ) {
$preB64 . Substring ( $i , [ Math ] :: Min ( $chunkSize , $preB64 . Length - $i ) )
}
$cmds = New-Object System . Collections . Generic . List [ string ]
# 1. Create the target dir.
$cmds . Add ( " cmd /c md "" $preDir "" 2>nul " )
# 2..N. Append each base64 chunk to the temp file.
foreach ( $c in $chunks ) {
$cmds . Add ( " cmd /c >> "" $preB64File "" echo $c " )
}
# N+1. Strip whitespace (chunks are newline-separated in the file) and decode.
$cmds . Add ( " powershell -nop -c "" [IO.File]::WriteAllBytes(' $preFile ',[Convert]::FromBase64String(((gc ' $preB64File ' -raw) -replace '\s',''))) "" " )
# N+2. Clean up the temp file.
$cmds . Add ( " cmd /c del "" $preB64File "" " )
# N+3 (LAST). Launch the SilverMetal toolbox (run-once).
$cmds . Add ( " cmd /c powershell -NoProfile -ExecutionPolicy Bypass -Command "" Start-Process -FilePath 'C:\Program Files\SilverOS\Welcome\SilverOS.Welcome.App.exe' -Verb RunAs "" " )
$firstLogonSb = New-Object System . Text . StringBuilder
$order = 0
foreach ( $cmd in $cmds ) {
$order + +
[ void ] $firstLogonSb . AppendLine ( " <SynchronousCommand wcm:action= "" add "" xmlns:wcm= "" http://schemas.microsoft.com/WMIConfig/2002/State "" > " )
[ void ] $firstLogonSb . AppendLine ( " <Order> $order </Order> " )
[ void ] $firstLogonSb . AppendLine ( " <CommandLine> $( EscContent $cmd ) </CommandLine> " )
[ void ] $firstLogonSb . AppendLine ( " </SynchronousCommand> " )
}
$firstLogonCommands = $firstLogonSb . ToString ( ) . TrimEnd ( )
@"
< ? x m l v e r s i o n = " 1 . 0 " e n c o d i n g = " u t f - 8 " ? >
@@ -64,17 +105,6 @@ function New-SmAnswerFile {
< U s e r D a t a > < A c c e p t E u l a > t r u e < / A c c e p t E u l a > < / U s e r D a t a >
< / c o m p o n e n t >
< / s e t t i n g s >
< s e t t i n g s p a s s = " s p e c i a l i z e " >
< c o m p o n e n t n a m e = " M i c r o s o f t - W i n d o w s - D e p l o y m e n t " p r o c e s s o r A r c h i t e c t u r e = " a m d 6 4 " p u b l i c K e y T o k e n = " 3 1 b f 3 8 5 6 a d 3 6 4 e 3 5 " l a n g u a g e = " n e u t r a l " v e r s i o n S c o p e = " n o n S x S " >
< R u n S y n c h r o n o u s >
< R u n S y n c h r o n o u s C o m m a n d w c m : a c t i o n = " a d d " x m l n s : w c m = " h t t p : / / s c h e m a s . m i c r o s o f t . c o m / W M I C o n f i g / 2 0 0 2 / S t a t e " >
< O r d e r > 1 < / O r d e r >
< P a t h > $( EscContent $writePre ) < / P a t h >
< D e s c r i p t i o n > W r i t e S i l v e r M e t a l p r e c o n f i g < / D e s c r i p t i o n >
< / R u n S y n c h r o n o u s C o m m a n d >
< / R u n S y n c h r o n o u s >
< / c o m p o n e n t >
< / s e t t i n g s >
< s e t t i n g s p a s s = " o o b e S y s t e m " >
< c o m p o n e n t n a m e = " M i c r o s o f t - W i n d o w s - I n t e r n a t i o n a l - C o r e " p r o c e s s o r A r c h i t e c t u r e = " a m d 6 4 " p u b l i c K e y T o k e n = " 3 1 b f 3 8 5 6 a d 3 6 4 e 3 5 " l a n g u a g e = " n e u t r a l " v e r s i o n S c o p e = " n o n S x S " >
< I n p u t L o c a l e > $InputLocale < / I n p u t L o c a l e > < S y s t e m L o c a l e > $SystemLocale < / S y s t e m L o c a l e >
@@ -91,11 +121,7 @@ function New-SmAnswerFile {
< A u t o L o g o n > < E n a b l e d > t r u e < / E n a b l e d > < L o g o n C o u n t > 1 < / L o g o n C o u n t > < U s e r n a m e > $un < / U s e r n a m e > < P a s s w o r d > < V a l u e > $pw < / V a l u e > < P l a i n T e x t > t r u e < / P l a i n T e x t > < / P a s s w o r d > < / A u t o L o g o n >
< C o m p u t e r N a m e > $cn < / C o m p u t e r N a m e >
< F i r s t L o g o n C o m m a n d s >
< S y n c h r o n o u s C o m m a n d w c m : a c t i o n = " a d d " x m l n s : w c m = " h t t p : / / s c h e m a s . m i c r o s o f t . c o m / W M I C o n f i g / 2 0 0 2 / S t a t e " >
< O r d e r > 1 < / O r d e r >
< C o m m a n d L i n e > c m d / c p o w e r s h e l l - N o P r o f i l e - E x e c u t i o n P o l i c y B y p a s s - C o m m a n d " S t a r t - P r o c e s s - F i l e P a t h ' C : \ P r o g r a m F i l e s \ S i l v e r O S \ W e l c o m e \ S i l v e r O S . W e l c o m e . A p p . e x e ' - V e r b R u n A s " < / C o m m a n d L i n e >
< D e s c r i p t i o n > L a u n c h S i l v e r M e t a l t o o l b o x ( r u n - o n c e ) < / D e s c r i p t i o n >
< / S y n c h r o n o u s C o m m a n d >
$firstLogonCommands
< / F i r s t L o g o n C o m m a n d s >
< R e g i s t e r e d O w n e r > S i l v e r M e t a l < / R e g i s t e r e d O w n e r > < R e g i s t e r e d O r g a n i z a t i o n > S i l v e r L A B S < / R e g i s t e r e d O r g a n i z a t i o n >
< / c o m p o n e n t >