]> vilimpoc.org git repositories - dotfiles/commitdiff
dotfiles: stop the UAC launch line mangling its own arguments
authorMax Vilimpoc <max@vilimpoc.org>
Sat, 29 Aug 2026 17:17:40 +0000 (19:17 +0200)
committerMax Vilimpoc <max@vilimpoc.org>
Tue, 1 Sep 2026 10:53:18 +0000 (12:53 +0200)
Adding -TraceUser to the elevated launch gave it a second quoted argument, and
the ""..""  doubling used to get quotes through cmd only survives ONE.  With
two, the quote-state parsing merges the tail into the -File value, so the
elevated PowerShell was handed

    -File "C:\...\setup-windows-with-uac.ps1 -TraceUser LATISLAB\Claude "

and refused it -- "failed because the file does not have a '.ps1' extension" --
exiting -196608 (0xFFFD0000) before Start-Transcript could run.  The batch file
then reported no elevated log and guessed at a cancelled UAC prompt, which is
the one thing that had not happened.

Both values now travel in the environment and the quotes the child needs are
built as [char]34 inside PowerShell, so the command line in the batch file
carries no quote characters of its own beyond the outer pair.

Exercised through cmd against a probe script in a directory with a space in its
name: -File binds, -TraceUser arrives as LATISLAB\Claude, and the child's exit
code still propagates.  Against the real script with -Verb RunAs dropped, it now
gets as far as the #Requires elevation check, which is where a non-elevated run
should stop.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMh8i2QzkHNdE3MkKfcaT6

setup-windows.bat

index 1d32adae6c50142d34c9a4067e72120ea16cec2e..250d4cbb0b128aa076e48fea67a6e4a5d5d8f648 100644 (file)
@@ -61,10 +61,20 @@ set "DOTNET_EXE=%ProgramFiles%\dotnet\dotnet.exe"
 @rem administrator's credentials runs the elevated half AS that administrator, so\r
 @rem it cannot see whose box this is; the account named here is the one it grants\r
 @rem non-elevated ETW collection rights to (xperf / wpr without a UAC prompt).\r
+@rem\r
+@rem The two values go through the environment, and the quotes the child needs\r
+@rem around them are built in PowerShell as [char]34, so the command line below\r
+@rem contains no embedded quote characters at all. Writing them inline as ""..""\r
+@rem works for ONE argument and quietly breaks at two: the quote-state parsing\r
+@rem swallows everything after the first into the -File value, and the elevated\r
+@rem PowerShell dies with "failed because the file does not have a '.ps1'\r
+@rem extension" and exit code -196608 (0xFFFD0000) before it can log a thing.\r
 set "UAC_LOG=%~dp0setup-windows-uac.log"\r
 if exist "%UAC_LOG%" del "%UAC_LOG%"\r
+set "UAC_SCRIPT=%~dp0setup-windows-with-uac.ps1"\r
+set "UAC_TRACE_USER=%USERDOMAIN%\%USERNAME%"\r
 \r
-powershell -NoProfile -Command "$p = Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','""%~dp0setup-windows-with-uac.ps1""','-TraceUser','""%USERDOMAIN%\%USERNAME%""' -Wait -PassThru; exit $p.ExitCode"\r
+powershell -NoProfile -Command "$q = [char]34; $p = Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File',($q + $env:UAC_SCRIPT + $q),'-TraceUser',($q + $env:UAC_TRACE_USER + $q) -Wait -PassThru; exit $p.ExitCode"\r
 set "UAC_RC=%ERRORLEVEL%"\r
 \r
 @rem --- Surface the elevated session's output (its window has already closed) ---\r