带有 Invoke-Expression 的 powershell 的 Stderr 和 stdout 没有输出或错误

Stderr and stdout for powershell with Invoke-Expression has no output or errors

我正在尝试从 运行 宁一个 java 过程中获取 stdoutstderr,并且看到了一种看起来很简单、很酷的方法,但它没有用:

$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 消息那样理想。

我什至尝试过这种精心设计的方法,但它甚至似乎没有运行我想的那样returns几乎是即时的过程,而且我知道正常过程任务需要几秒钟。它还显示没有输出或错误:

$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"
(tried: adding:
do

    $process.StandardOutput.ReadLine()
}
while (!$process.HasExited)

注意:下面的解决方案假定一个行为良好的外部实用程序:将 data 发送到 stdout 的实用程序, 错误消息stderr。如果给定的实用程序意外地将错误消息发送到 stdout,就像 OP 的情况一样,您必须自己解析 stdout 输出以提取错误消息。

$stdout = java -jar secretserver-jconsole.jar -s 123456 Password 2>($tmpFile=New-TemporaryFile)
$stderr = Get-Content $tmpFile; Remove-Item $tmpFile

New-TemporaryFile 需要 PSv5,但您可以在早期版本中使用 [io.path]::GetTempFileName()

请注意,$stdout$stderr 都将包含一个字符串 数组 ,每个项目代表一个输出行。

外部实用程序的 退出代码 反映在 PowerShell 的自动 $LASTEXITCODE 变量中。

请注意,捕获 stdout 和 stderr 组合 实际上更容易:

$stdoutAndStdErr = java -jar secretserver-jconsole.jar -s 123456 Password 2>&1

注意:每个 stderr 行在结果中都表示为一个 [System.Management.Automation.ErrorRecord] 实例,但它们的计算结果为 contents字符串上下文。


至于你尝试了什么:

通常不需要将命令存储在 字符串 中(因此很少需要使用 Invoke-Expression,其使用可能有风险)。

  • 或者:直接调用外部命令行(注意 PowerShell 可能不需要的命令行解释;在 PSv3 中,--% 关闭 PowerShell 的解释 - 参见 Get-Help about_Parsing),
  • 或者,如果您需要先将命令存储在变量中,请使用 脚本块 ($cmd = { ... }),稍后使用 [=22= 调用它](调用运算符)或 .(点源运算符)- 前者为 PS 变量创建子作用域,后者则没有。

-OutVariable-ErrorVariable 通用参数仅设计用于 PowerShell 的 输出流,而不是外部世界的 stdout 和 stderr。

  • PowerShell 捕获 stdout 输出,就好像它已被发送到 PowerShell 的成功输出流一样,并将输出行视为 字符串数组 .

  • Stderr 输出被传递(并且未反映在 $Error 中),但您可以将其重定向到带有 2>$file 的文件,或者您可以将其合并到2>&1 的成功流(在这种情况下,每个 stderr 行都表示为一个 [System.Management.Automation.ErrorRecord] 实例)。