fix: CLIXML-Fehler bei Remote-Tool-Ausführung auf Windows beheben
Statt powershell.exe als Kindprozess mit 2>&1 zu starten (was CLIXML-Parsing-Fehler bei rohem stderr verursacht), wird System.Diagnostics.Process direkt verwendet. Zusätzlich werden harmlose CLIXML-Progress-Meldungen aus stderr herausgefiltert. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
f03fbd298e
commit
55477742a9
1 file changed
+29
-9
+29
-9
@@ -117,21 +117,41 @@ try {
|
|||||||
$stderr = ""
|
$stderr = ""
|
||||||
|
|
||||||
try {
|
try {
|
||||||
# EncodedCommand umgeht alle Quoting-Probleme (Anführungszeichen, Sonderzeichen)
|
# Process direkt starten um CLIXML-Parsing-Fehler bei stderr zu vermeiden
|
||||||
$encodedCmd = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($command))
|
$encodedCmd = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($command))
|
||||||
$output = & powershell.exe -NoProfile -NonInteractive -EncodedCommand $encodedCmd 2>&1
|
$proc = New-Object System.Diagnostics.Process
|
||||||
$stdoutLines = @($output | Where-Object { $_ -isnot [System.Management.Automation.ErrorRecord] })
|
$proc.StartInfo.FileName = "powershell.exe"
|
||||||
$stderrLines = @($output | Where-Object { $_ -is [System.Management.Automation.ErrorRecord] }) |
|
$proc.StartInfo.Arguments = "-NoProfile -NonInteractive -EncodedCommand $encodedCmd"
|
||||||
ForEach-Object { $_.ToString() }
|
$proc.StartInfo.RedirectStandardOutput = $true
|
||||||
$stdout = ($stdoutLines | Out-String).TrimEnd()
|
$proc.StartInfo.RedirectStandardError = $true
|
||||||
$stderr = ($stderrLines | Out-String).TrimEnd()
|
$proc.StartInfo.UseShellExecute = $false
|
||||||
$exitCode = $LASTEXITCODE
|
$proc.StartInfo.CreateNoWindow = $true
|
||||||
if ($null -eq $exitCode) { $exitCode = 0 }
|
$proc.Start() | Out-Null
|
||||||
|
# stderr async lesen um Deadlocks zu vermeiden
|
||||||
|
$stderrTask = $proc.StandardError.ReadToEndAsync()
|
||||||
|
$stdout = $proc.StandardOutput.ReadToEnd()
|
||||||
|
$stderrTask.Wait()
|
||||||
|
$stderr = $stderrTask.Result
|
||||||
|
$proc.WaitForExit()
|
||||||
|
$exitCode = $proc.ExitCode
|
||||||
|
$proc.Dispose()
|
||||||
} catch {
|
} catch {
|
||||||
$stderr = $_.Exception.Message
|
$stderr = $_.Exception.Message
|
||||||
$exitCode = 1
|
$exitCode = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# CLIXML-Progress aus stderr filtern (PowerShell schreibt Modul-Lade-Fortschritt als CLIXML)
|
||||||
|
if ($stderr -and $stderr.StartsWith("#< CLIXML")) {
|
||||||
|
$cleanLines = @()
|
||||||
|
foreach ($line in ($stderr -split "`n")) {
|
||||||
|
$trimmed = $line.Trim()
|
||||||
|
if ($trimmed -eq "#< CLIXML") { continue }
|
||||||
|
if ($trimmed -match '^\<Objs .+\<PR N="Record"\>.*\<T\>Completed\</T\>') { continue }
|
||||||
|
if ($trimmed -ne "") { $cleanLines += $line }
|
||||||
|
}
|
||||||
|
$stderr = ($cleanLines -join "`n").Trim()
|
||||||
|
}
|
||||||
|
|
||||||
# Ergebnis senden
|
# Ergebnis senden
|
||||||
$response = @{
|
$response = @{
|
||||||
type = "result"
|
type = "result"
|
||||||
|
|||||||
Reference in new issue
Block a user