2014-04-23 44 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',因爲直到進程完成後纔會生成輸出。 –

相關問題