2014-04-23 23 views
6

我正在使用PowerShell脚本来执行控制台应用程序,我试图从那里重定向标准输出和标准错误。 我使用的代码如下:PowerShell,流在运行外部进程时处理输出和错误

$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo 
$ProcessInfo.FileName = "myExe.exe" 
$ProcessInfo.Arguments = "bla bla bla" 
$ProcessInfo.RedirectStandardError = $true 
$ProcessInfo.RedirectStandardOutput = $true 
$ProcessInfo.UseShellExecute = $false 
$Process = New-Object System.Diagnostics.Process 
$Process.StartInfo = $ProcessInfo 

$Process.Start() | Out-Null 
$output = $Process.StandardOutput.ReadToEnd() 
$errors = $Process.StandardError.ReadToEnd() 
$Process.WaitForExit() 
$output 
$errors 

return $Process.ExitCode 

到目前为止好,如果我有一个错误,我可以看到它重定向到我PowerShell控制台,如果我有它输出也被重新定向。 问题是这个过程需要10分钟,同时我们不知道发生了什么。

有没有什么办法可以在PowerShell中我可以输出和错误的内容,当进程正在运行?在纯.NET中,我们可以订阅Process类的事件,我可以在PowerShell中执行相同的操作吗?

回答

9

在PowerShell中有什么方法我可以在流程运行时流式输出和错误的内容?在纯.NET中,我们可以订阅Process类的事件,我可以在PowerShell中执行相同的操作吗?

当然可以!你需要的是一个Object Events

对象事件是一个.NET对象,它不仅具有一般的属性方法的对象,同时也呼吁事件其他成员,你可以在使用时注册订阅Register-ObjectEvent

这里是从PowerShell forums稍作修改的示例。它将以异步方式从ping命令输出数据(at least from the script point of view):

# Setup stdin\stdout redirection 
$StartInfo = New-Object System.Diagnostics.ProcessStartInfo -Property @{ 
       FileName = 'ping.exe' 
       Arguments = '-t 127.0.0.1' 
       UseShellExecute = $false 
       RedirectStandardOutput = $true 
       RedirectStandardError = $true 
      } 

# Create new process 
$Process = New-Object System.Diagnostics.Process 

# Assign previously created StartInfo properties 
$Process.StartInfo = $StartInfo 

# Register Object Events for stdin\stdout reading 
$OutEvent = Register-ObjectEvent -InputObject $Process -EventName OutputDataReceived -Action { 
    Write-Host $Event.SourceEventArgs.Data 
} 
$ErrEvent = Register-ObjectEvent -InputObject $Process -EventName ErrorDataReceived -Action { 
    Write-Host $Event.SourceEventArgs.Data 
} 

# Start process 
[void]$Process.Start() 

# Begin reading stdin\stdout 
$Process.BeginOutputReadLine() 
$Process.BeginErrorReadLine() 

# Do something else while events are firing 
do 
{ 
    Write-Host 'Still alive!' -ForegroundColor Green 
    Start-Sleep -Seconds 1 
} 
while (!$Process.HasExited) 

# Unregister events 
$OutEvent.Name, $ErrEvent.Name | 
    ForEach-Object {Unregister-Event -SourceIdentifier $_} 
+2

只是一个快速的评论。不要考虑在进程中调用'WaitForExit',因为直到进程完成后才会生成输出。 –

相关问题