Powershell:使用Process对象捕获标准输出和错误

时间:2012-07-17 21:21:39

标签: java windows powershell

我想从PowerShell启动一个Java程序,并在控制台上打印结果。

我已按照此问题的说明操作: Capturing standard out and error with Start-Process

但对我来说,这不符合我的预期。我做错了什么?

这是剧本:

$psi = New-object System.Diagnostics.ProcessStartInfo
$psi.CreateNoWindow = $true
$psi.UseShellExecute = $false
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError = $true
$psi.FileName = 'java.exe'
$psi.Arguments = @("-jar","tools\compiler.jar","--compilation_level",   "ADVANCED_OPTIMIZATIONS", "--js", $BuildFile, "--js_output_file", $BuildMinFile)
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $psi
$process.Start() | Out-Null
$process.WaitForExit()
$output = $process.StandardOutput.ReadToEnd()
$output

$output变量始终为空(当然,控制台上没有打印任何内容)。

3 个答案:

答案 0 :(得分:36)

RedirectStandardError媒体资源上的文档表明,最好在WaitForExit()电话后发出ReadToEnd()来电。以下对我来说正常:

$psi = New-object System.Diagnostics.ProcessStartInfo 
$psi.CreateNoWindow = $true 
$psi.UseShellExecute = $false 
$psi.RedirectStandardOutput = $true 
$psi.RedirectStandardError = $true 
$psi.FileName = 'ipconfig.exe' 
$psi.Arguments = @("/a") 
$process = New-Object System.Diagnostics.Process 
$process.StartInfo = $psi 
[void]$process.Start()
$output = $process.StandardOutput.ReadToEnd() 
$process.WaitForExit() 
$output

答案 1 :(得分:14)

小变化,以便您可以根据需要选择性地打印输出。如果您只是寻找错误或警告信息,并且按照Keith的方式保存我的培根以及您的回复...

$psi = New-object System.Diagnostics.ProcessStartInfo 
$psi.CreateNoWindow = $true 
$psi.UseShellExecute = $false 
$psi.RedirectStandardOutput = $true 
$psi.RedirectStandardError = $true 
$psi.FileName = 'robocopy' 
$psi.Arguments = @("$HomeDirectory $NewHomeDirectory /MIR /XF desktop.ini /XD VDI /R:0 /W:0 /s /v /np") 
$process = New-Object System.Diagnostics.Process 
$process.StartInfo = $psi 
[void]$process.Start()
do
{
   $process.StandardOutput.ReadLine()
}
while (!$process.HasExited)

答案 2 :(得分:1)

这里是对保罗的回答的修改,希望它可以解决截断的输出。我使用失败进行了测试,但没有看到截断。

function Start-ProcessWithOutput
{
    param ([string]$Path,[string[]]$ArgumentList)
    $Output = New-Object -TypeName System.Text.StringBuilder
    $Error = New-Object -TypeName System.Text.StringBuilder
    $psi = New-object System.Diagnostics.ProcessStartInfo 
    $psi.CreateNoWindow = $true 
    $psi.UseShellExecute = $false 
    $psi.RedirectStandardOutput = $true 
    $psi.RedirectStandardError = $true 
    $psi.FileName = $Path
    if ($ArgumentList.Count -gt 0)
    {
        $psi.Arguments = $ArgumentList
    }
    $process = New-Object System.Diagnostics.Process 
    $process.StartInfo = $psi 
    [void]$process.Start()
    do
    {


       if (!$process.StandardOutput.EndOfStream)
       {
           [void]$Output.AppendLine($process.StandardOutput.ReadLine())
       }
       if (!$process.StandardError.EndOfStream)
       {
           [void]$Error.AppendLine($process.StandardError.ReadLine())
       }
       Start-Sleep -Milliseconds 10
    } while (!$process.HasExited)

    #read remainder
    while (!$process.StandardOutput.EndOfStream)
    {
        #write-verbose 'read remaining output'
        [void]$Output.AppendLine($process.StandardOutput.ReadLine())
    }
    while (!$process.StandardError.EndOfStream)
    {
        #write-verbose 'read remaining error'
        [void]$Error.AppendLine($process.StandardError.ReadLine())
    }

    return @{ExitCode = $process.ExitCode; Output = $Output.ToString(); Error = $Error.ToString(); ExitTime=$process.ExitTime}
}


$p = Start-ProcessWithOutput "C:\Program Files\7-Zip\7z.exe" -ArgumentList "x","-y","-oE:\PowershellModules",$NewModules.FullName -verbose
$p.ExitCode
$p.Output
$p.Error

10毫秒的睡眠是为了避免在没有内容可读取时使cpu旋转。