All checks were successful
Build SilverMetal Enhanced - Windows ISO / build (pull_request) Successful in 4m39s
2nd VM e2e: Shell Launcher config still failed with 'Type mismatch for parameter DefaultAction'. WESL_UserSetting.SetCustomShell/SetDefaultShell take sint32 (Int32) DefaultAction, but we passed [uint32]0. The fail-open rollback worked (no brick, booted to Explorer) but the kiosk never engaged. Pass [int32]0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
81 lines
4.9 KiB
PowerShell
81 lines
4.9 KiB
PowerShell
#Requires -Version 5.1
|
|
<#
|
|
.SYNOPSIS Configure the one-time sm-bootstrap onboarding kiosk.
|
|
.DESCRIPTION
|
|
Runs from SetupComplete.cmd as SYSTEM, after accounts exist, before first
|
|
logon. Sets the sm-bootstrap shell to an elevating launcher for the Welcome
|
|
app (no Explorer => no taskbar/Start), turns on the Keyboard Filter for shell
|
|
hotkeys, and disables Task Manager / lock / fast-user-switch escapes.
|
|
Reverted by the Welcome app's ApplyService on wizard success.
|
|
#>
|
|
[CmdletBinding()]
|
|
param([string]$BootstrapUser='sm-bootstrap',
|
|
[string]$WelcomeExe='C:\Program Files\SilverOS\Welcome\SilverOS.Welcome.App.exe')
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference='Stop'
|
|
$log='C:\Windows\Setup\Scripts\silvermetal-kiosk.log'
|
|
function Log($m){ "$(Get-Date -f s) $m" | Add-Content $log }
|
|
|
|
# Elevating launcher: Shell Launcher runs this as the shell; it relaunches the
|
|
# Welcome app elevated (silent via the baked UAC auto-approve).
|
|
$launcher='C:\Windows\Setup\Scripts\Start-WelcomeShell.cmd'
|
|
$welcomeEscaped = $WelcomeExe.Replace("'","''")
|
|
@"
|
|
@echo off
|
|
powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -LiteralPath '$welcomeEscaped' -Verb RunAs"
|
|
REM Shell Launcher tracks this CMD process; the Welcome app runs detached above.
|
|
REM Loop keeps the process alive so Shell Launcher doesn't restart it on idle.
|
|
:loop
|
|
timeout /t 3600 >nul
|
|
goto loop
|
|
"@ | Set-Content $launcher -Encoding ASCII
|
|
Log "wrote launcher $launcher"
|
|
|
|
# --- Shell Launcher v2 (WMI bridge) ---
|
|
# WESL_UserSetting exposes STATIC methods on the CLASS — Get-CimInstance returns
|
|
# no instance, so every method must be called class-level (-Namespace/-ClassName),
|
|
# NOT via -InputObject on a (null) instance. Getting this wrong enables Shell
|
|
# Launcher with NO shell configured, which bricks EVERY logon (incl. OOBE's
|
|
# defaultuser0) into a reboot loop. So: set the DEFAULT shell to explorer.exe for
|
|
# all users first (this is what keeps OOBE/normal logons working), set the
|
|
# sm-bootstrap custom shell, and roll back SetEnabled(false) + fall back to a
|
|
# RunOnce launch if anything fails — never leave SL enabled-but-unconfigured.
|
|
$cls='root\standardcimv2\embedded'
|
|
$sid=(New-Object System.Security.Principal.NTAccount($BootstrapUser)).Translate([System.Security.Principal.SecurityIdentifier]).Value
|
|
try {
|
|
Invoke-CimMethod -Namespace $cls -ClassName WESL_UserSetting -MethodName SetEnabled -Arguments @{Enabled=$true} | Out-Null
|
|
# Default shell = Explorer for everyone else (incl. OOBE) — critical so non-kiosk logons don't break.
|
|
Invoke-CimMethod -Namespace $cls -ClassName WESL_UserSetting -MethodName SetDefaultShell -Arguments @{Shell='explorer.exe';DefaultAction=[int32]0} | Out-Null
|
|
# sm-bootstrap => the elevating launcher; on exit, restart the shell (action 0).
|
|
Invoke-CimMethod -Namespace $cls -ClassName WESL_UserSetting -MethodName SetCustomShell -Arguments @{
|
|
Sid=$sid; Shell="cmd.exe /c `"$launcher`""; DefaultAction=[int32]0 } | Out-Null
|
|
$set=Invoke-CimMethod -Namespace $cls -ClassName WESL_UserSetting -MethodName GetCustomShell -Arguments @{Sid=$sid} -ErrorAction SilentlyContinue
|
|
if (-not $set -or [string]::IsNullOrEmpty($set.Shell)) { throw "custom shell did not take for $BootstrapUser" }
|
|
Log "shell launcher configured for sm-bootstrap (shell=$($set.Shell))"
|
|
}
|
|
catch {
|
|
Log "SHELL LAUNCHER CONFIG FAILED: $($_.Exception.Message) -- rolling back (SetEnabled false) + RunOnce fallback so onboarding still launches"
|
|
Invoke-CimMethod -Namespace $cls -ClassName WESL_UserSetting -MethodName SetEnabled -Arguments @{Enabled=$false} -ErrorAction SilentlyContinue | Out-Null
|
|
# Fail-OPEN: no kiosk, but the Welcome wizard must still launch (we removed FirstLogonCommands).
|
|
$ro='HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce'
|
|
New-Item $ro -Force | Out-Null
|
|
Set-ItemProperty $ro -Name 'SilverOSWelcome' -Type String -Value "cmd /c powershell -NoProfile -ExecutionPolicy Bypass -Command `"Start-Process -LiteralPath '$welcomeEscaped' -Verb RunAs`""
|
|
}
|
|
|
|
# --- Keyboard Filter (block shell hotkeys) ---
|
|
Enable-WindowsOptionalFeature -Online -FeatureName Client-KeyboardFilter -NoRestart -ErrorAction SilentlyContinue | Out-Null
|
|
$kf='root\standardcimv2\embedded'
|
|
foreach($combo in 'Win','Win+L','Ctrl+Esc','Ctrl+Win+F','Win+R'){
|
|
$p=Get-CimInstance -Namespace $kf -ClassName WEKF_PredefinedKey -Filter "Id='$combo'" -ErrorAction SilentlyContinue
|
|
if($p){ $p.Enabled=$true; Set-CimInstance -InputObject $p }
|
|
}
|
|
Log 'keyboard filter rules enabled'
|
|
|
|
# --- escape policies (machine-wide; reverted at teardown) ---
|
|
$sys='HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
|
|
New-Item $sys -Force | Out-Null
|
|
Set-ItemProperty $sys -Name DisableTaskMgr -Value 1 -Type DWord
|
|
Set-ItemProperty $sys -Name DisableLockWorkstation -Value 1 -Type DWord
|
|
Set-ItemProperty $sys -Name HideFastUserSwitching -Value 1 -Type DWord
|
|
Log 'escape policies set; kiosk ready'
|