在使用 Invoke-Expression 命令执行 PowerShell 时,标准错误流(Stderr)和标准输出流(Stdout)没有任何输出或错误。
在使用 Invoke-Expression 命令执行 PowerShell 时,标准错误流(Stderr)和标准输出流(Stdout)没有任何输出或错误。
我正试图从运行的Java进程中获取stdout和stderr,并且看到了一个看起来很简单、很酷的方法,但它没有起作用:
$command = "java -jar secretserver-jconsole.jar -s 123456 Password"
Invoke-Expression $command -OutVariable output -ErrorVariable errors
Write-Host "stdout: $output"
Write-Host "stderr: $errors"
没有显示任何$output或$errors。
我现在使用的是:
$output = cmd /c $command
虽然这确实给我一些stdout,但不理想,因为我想要$error消息。
我甚至尝试了这种复杂的方法,但它似乎甚至没有运行我认为的进程,因为返回几乎是瞬间的,而我知道正常的进程需要几秒钟。它也没有显示任何输出或错误:
$psi = New-object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.FileName = 'java'
$psi.Arguments = @("-jar","secretserver-jconsole.jar","-s","123456","Password")
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi
[void]$process.Start()
$output = $process.StandardOutput.ReadToEnd()
$process.WaitForExit()
Write-Host "stdout: $output"
(尝试:添加:
do
$process.StandardOutput.ReadLine()
}
while (!$process.HasExited)
问题原因:外部工具发送错误消息到stdout而不是stderr。
解决方法:
1. 使用以下代码将stdout和stderr分别存储到变量中:
$stdout = java -jar secretserver-jconsole.jar -s 123456 Password 2>($tmpFile=New-TemporaryFile) $stderr = Get-Content $tmpFile; Remove-Item $tmpFile
注意,$stdout和$stderr将包含一个字符串数组,每个条目表示一行输出。
2. 使用以下代码将stdout和stderr合并到一个变量中:
$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1
注意,合并后的stdout和stderr将作为字符串的数组表示。
补充说明:
- 外部工具的退出码可以通过PowerShell的自动变量$LASTEXITCODE获取。
- 使用-OutVariable和-ErrorVariable参数只能捕获PowerShell的输出流,而无法捕获外部工具的stdout和stderr。
- 如果外部工具发送错误消息到stdout而不是stderr,需要自己解析stdout输出以提取错误消息。
出现问题的原因是使用Invoke-Expression命令存储命令字符串并执行。实际上,可以直接执行外部命令,并使用字符串数组或脚本块存储命令。
文章结束。