使用Invoke-Expression的PowerShell的Stderr和stdout没有输出或错误

时间:2017-05-04 13:47:34

标签: powershell stdout stderr

我正在尝试让stdoutstderr运行java进程,并且看到了一个简单,酷炫的方法,但它不起作用:

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

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

1 个答案:

答案 0 :(得分:3)

注意:下面的解决方案假定一个行为良好的外部实用程序:一个将数据发送到 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都将包含字符串 array ,每个项目代表一个输出行。

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

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

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

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

至于你的尝试:

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

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

-OutVariable-ErrorVariable常用参数仅适用于 PowerShell的输出流,而非外部世界的stdout和stderr。

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

  • Stderr输出传递(并且不会反映在$Error中),但您可以将其重定向到2>$file的文件,或者您可以使用{将其合并到成功流中{1}}(在这种情况下,stderr行每个都表示为2>&1个实例)。