All checks were successful
Build SilverMetal Enhanced - Windows ISO / build (pull_request) Successful in 7m31s
5th VM e2e: with the kiosk fully working mechanically (SL engages, silent UAC, app launches fullscreen as the shell), the MAUI/WebView2 wizard STILL renders blank — WebView2 never initializes when the app is the bare Shell Launcher shell with no Explorer (the same app rendered fine in the earlier build launched with Explorer present). Operator decision: pivot. - autounattend.xml: restore FirstLogonCommands to launch the wizard elevated over the normal (Explorer) first-logon session — where WebView2 works. - Configure-Kiosk.ps1: drop Shell-Launcher-as-shell entirely; keep the lockdown — Keyboard Filter (Win/Start/lock/task-switch/Task-Mgr/Alt+F4), DisableTaskMgr / LockWorkstation / FastUserSwitch, and silent-elevation UAC. The wizard runs fullscreen-topmost over the locked-down Explorer (covers the taskbar). - RevertKioskAsync: disable the Keyboard Filter rules for the real user (no SL to undo); keep escape-policy + secure-UAC restore. Tests updated. Keeps the diagnostics from #10 (welcome.log) to confirm the wizard renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
2.9 KiB
C#
45 lines
2.9 KiB
C#
namespace SilverOS.Welcome.Core.Apply;
|
|
public sealed class BootstrapService(IProcessRunner runner) : IBootstrapService
|
|
{
|
|
// Lockdown revert is BEST-EFFORT (like TearDownAsync): -EA SilentlyContinue throughout.
|
|
// Don't fail the apply over a missing WMI class / key. Must run BEFORE TearDownAsync.
|
|
public async Task RevertKioskAsync(CancellationToken ct = default)
|
|
{
|
|
// Disable the Keyboard Filter rules so the real end-user's Win key / task-switch /
|
|
// Alt+F4 etc. work again (Explorer is already the shell — nothing to undo there).
|
|
await Ps(
|
|
"$c='root\\\\standardcimv2\\\\embedded';" +
|
|
"foreach($k in @('Win','Win+L','Ctrl+Esc','Ctrl+Win+F','Win+R','Alt+Tab','Ctrl+Shift+Esc','Alt+F4')){" +
|
|
"$p=Get-CimInstance -Namespace $c -ClassName WEKF_PredefinedKey -Filter \"Id='$k'\" -EA SilentlyContinue;" +
|
|
"if($p){$p.Enabled=$false; Set-CimInstance -InputObject $p -EA SilentlyContinue}" +
|
|
"}",
|
|
ct);
|
|
// Revert escape policies set by Configure-Kiosk.ps1.
|
|
await Ps(
|
|
"$s='HKLM:\\\\SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Policies\\\\System';" +
|
|
"Remove-ItemProperty $s -Name DisableTaskMgr,DisableLockWorkstation,HideFastUserSwitching -EA SilentlyContinue;" +
|
|
// Restore SECURE UAC for the real end-user (the kiosk auto-approved unsigned elevation).
|
|
"Set-ItemProperty $s -Name ConsentPromptBehaviorAdmin -Value 2 -Type DWord -EA SilentlyContinue;" +
|
|
"Set-ItemProperty $s -Name PromptOnSecureDesktop -Value 1 -Type DWord -EA SilentlyContinue",
|
|
ct);
|
|
}
|
|
|
|
// Teardown is BEST-EFFORT (unlike Account/BitLocker which are strict): the answer file's
|
|
// AutoLogon LogonCount=1 already neutralises auto-logon after the first logon (Windows clears
|
|
// AutoAdminLogon itself), so these Winlogon cleanups must not fail the whole apply. The op that
|
|
// matters — removing the sm-bootstrap account — runs regardless and is tolerant too.
|
|
public async Task TearDownAsync(string bootstrapUser, CancellationToken ct = default)
|
|
{
|
|
const string w = "'HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon'";
|
|
await Ps($"Set-ItemProperty -Path {w} -Name AutoAdminLogon -Value '0' -EA SilentlyContinue; " +
|
|
$"Remove-ItemProperty -Path {w} -Name DefaultPassword -EA SilentlyContinue; " +
|
|
$"Remove-ItemProperty -Path {w} -Name DefaultUserName -EA SilentlyContinue; " +
|
|
$"Remove-ItemProperty -Path {w} -Name DefaultDomainName -EA SilentlyContinue", ct);
|
|
var u = Esc(bootstrapUser);
|
|
await Ps($"Remove-LocalUser -Name '{u}' -EA SilentlyContinue", ct);
|
|
}
|
|
private static string Esc(string s) => s.Replace("'", "''");
|
|
private Task Ps(string s, CancellationToken ct) =>
|
|
runner.RunAsync("powershell.exe", $"-NoProfile -ExecutionPolicy Bypass -Command \"{s}\"", ct);
|
|
}
|