我正在尝试让stdout
和stderr
运行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)
答案 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的解释 - 请参阅Get-Help about_Parsing
),$cmd = { ... }
),稍后使用&
(调用运算符)调用它或.
(点源运算符) - 前者为PS变量创建子范围,后者则不创建。{/ li>
-OutVariable
和-ErrorVariable
常用参数仅适用于 PowerShell的输出流,而非外部世界的stdout和stderr。
PowerShell捕获stdout输出,就像它已发送到PowerShell的成功输出流一样,并将输出行视为字符串数组。
Stderr输出传递(并且不会反映在$Error
中),但您可以将其重定向到2>$file
的文件,或者您可以使用{将其合并到成功流中{1}}(在这种情况下,stderr行每个都表示为2>&1
个实例)。