Skip to content

Commit a6abcdb

Browse files
Peter HaugeCopilot
andcommitted
fix: resolve cmd.exe quoting and stdin issues in Invoke-MaskedProcess
When Invoke-MaskedProcess runs inside Start-Job (a separate process), two issues caused failures on Windows: 1. RedirectStandardInput was false, so child processes inherited a broken stdin handle from the job's consoleless process, causing Python (az CLI) to hang on startup. Fixed by redirecting stdin and closing it immediately. 2. ArgumentList individually quotes each argument, but cmd.exe /c has its own quoting rules that conflict. Paths with spaces (C:\Program Files\...) broke, and metacharacters like parentheses in JMESPath queries were interpreted as cmd.exe grouping operators. Fixed by using the Arguments string property with proper quoting for the cmd.exe /c case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 31b9bef commit a6abcdb

1 file changed

Lines changed: 21 additions & 4 deletions

File tree

tests/integration/all-resource-types/modules/LogMasking.psm1

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,20 +261,36 @@ function Invoke-MaskedProcess {
261261
)
262262

263263
$exe = Resolve-NativeExecutable -Name $FilePath
264-
$finalArgs = @() + $exe.Prefix + $Arguments
265264

266265
$psi = [System.Diagnostics.ProcessStartInfo]::new()
267266
$psi.FileName = $exe.FilePath
268267
$psi.RedirectStandardOutput = $true
269268
$psi.RedirectStandardError = $true
270-
$psi.RedirectStandardInput = $false
269+
$psi.RedirectStandardInput = $true
271270
$psi.UseShellExecute = $false
272271
$psi.CreateNoWindow = $true
273272
$psi.StandardOutputEncoding = [System.Text.Encoding]::UTF8
274273
$psi.StandardErrorEncoding = [System.Text.Encoding]::UTF8
275274

276-
foreach ($a in $finalArgs) {
277-
[void]$psi.ArgumentList.Add([string]$a)
275+
if ($exe.Prefix.Count -ge 2 -and $exe.Prefix[0] -eq '/c') {
276+
# cmd.exe /c has special quoting rules that conflict with ArgumentList.
277+
# Use the Arguments string property with double-quote wrapping so cmd.exe
278+
# preserves the inner quotes around paths that contain spaces.
279+
$cmdTarget = $exe.Prefix[1]
280+
$quotedParts = @("`"$cmdTarget`"")
281+
foreach ($a in $Arguments) {
282+
$s = [string]$a
283+
# Quote every argument individually so cmd.exe treats all content
284+
# (including metacharacters like parentheses) as literals.
285+
$escaped = $s -replace '"', '\"'
286+
$quotedParts += "`"$escaped`""
287+
}
288+
$psi.Arguments = "/c `"$($quotedParts -join ' ')`""
289+
} else {
290+
$finalArgs = @() + $exe.Prefix + $Arguments
291+
foreach ($a in $finalArgs) {
292+
[void]$psi.ArgumentList.Add([string]$a)
293+
}
278294
}
279295

280296
$stdoutQueue = [System.Collections.Concurrent.ConcurrentQueue[string]]::new()
@@ -305,6 +321,7 @@ function Invoke-MaskedProcess {
305321

306322
try {
307323
[void]$proc.Start()
324+
$proc.StandardInput.Close()
308325

309326
$outJob = Start-ThreadJob -ScriptBlock $readerScript -ArgumentList $proc.StandardOutput, $stdoutQueue
310327
$errJob = Start-ThreadJob -ScriptBlock $readerScript -ArgumentList $proc.StandardError, $stderrQueue

0 commit comments

Comments
 (0)