Java Powershell:捕获进程对象的标准输出和错误

Java Powershell:捕获进程对象的标准输出和错误,java,windows,powershell,Java,Windows,Powershell,我想从PowerShell启动一个Java程序,并在控制台上打印结果 我已按照这个问题的指示: 但对我来说,这并不像我预期的那样有效。我做错了什么 以下是脚本: $psi = New-object System.Diagnostics.ProcessStartInfo $psi.CreateNoWindow = $true $psi.UseShellExecute = $false $psi.RedirectStandardOutput = $true $psi.RedirectStandar

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

我已按照这个问题的指示:

但对我来说,这并不像我预期的那样有效。我做错了什么

以下是脚本:

$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
变量始终为空(当然控制台上不会打印任何内容)。

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

小的变化,以便您可以有选择地打印输出,如果需要的话。就好像你只是在寻找错误或警告信息,顺便说一句,基思,你的回答拯救了我的培根

$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)

这里是对paul答案的修改,希望它能解决被截断的输出。我使用失败进行了测试,没有看到截断

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旋转。

考虑到PowerShell是一个“shell”,您为什么不执行
PS>java.exe-jar-tools\compiler.jar--compile_level…
?它实际上可以工作:),但我仍然不明白上面的脚本为什么不将输出打印到控制台@dev使用Write OutPut$OutPut,查看通过带有完整源代码示例应用程序的consoleAny最终解决方案返回的内容?IMHO,最小化学习曲线的更好示例是具有完整源代码和良好模式的真实应用程序。啊,我使用| Out Null来防止控制台上打印“true”。@devundef忽略关于管道输出为Null的注释。这里没问题。“管道输出空值”技巧可用于延迟,直到您启动的Windows exe关闭,即
Notepad.exe | Out Null
。这不适用于您的情况。我很确定Windows也不允许您跨管理/非管理安全边界重定向标准输入/输出/错误。您必须找到一种不同的方式来获取以管理员身份运行的程序的输出:我非常确定Windows也不允许您跨管理员/非管理员安全边界重定向标准输入/输出/错误。您必须找到一种不同的方式从作为管理员引用运行的程序中获取输出:您重复读取输出缓冲区的方式是关键。否则,生成大文本的进程可以填充输出缓冲区,程序将手动执行。唯一需要做的更改是将读取行附加到一个字符串以供以后使用。我在这种方法中遇到了问题,例如,当进程由于错误而退出时,ReadLine()无法跟上,因此输出被截断。这是一个很好的解决死锁的方法,以“正确”的方式执行此操作。