2014-04-23 14 views
6

Tôi đang sử dụng tập lệnh PowerShell để thực thi ứng dụng bảng điều khiển và tôi đang cố chuyển hướng đầu ra tiêu chuẩn và lỗi chuẩn từ đó. Mã Tôi đang sử dụng như sau:PowerShell, stream Quy trình xuất và lỗi khi chạy quá trình bên ngoài

$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 

Cho đến nay rất tốt, nếu tôi có một lỗi tôi có thể nhìn thấy nó chuyển vào giao diện điều khiển PowerShell của tôi và nếu tôi có đầu ra nó cũng được chuyển hướng. Vấn đề là quá trình này mất 10 phút và trong khi chờ đợi chúng tôi không có đầu mối về những gì đang diễn ra.

Có cách nào trong PowerShell tôi có thể dòng nội dung của Đầu ra và Lỗi trong khi quá trình đang chạy không? Trong .NET thuần túy, chúng ta có thể đăng ký các sự kiện của lớp Process, tôi có thể thực hiện tương tự trong PowerShell không?

Trả lời

9

Có cách nào trong PowerShell tôi có thể truyền nội dung của Đầu ra và Lỗi trong khi quá trình đang chạy không? Trong .NET thuần túy, chúng ta có thể đăng ký các sự kiện của lớp Process, tôi có thể thực hiện tương tự trong PowerShell không?

Chắc chắn bạn có thể! Những gì bạn cần là một Object Events:

Một sự kiện đối tượng là một đối tượng Net rằng không chỉ có bình thường Thuộc tínhPhương pháp trong đối tượng, nhưng cũng đã một thành viên khác gọi là Event, mà bạn có thể đăng ký thuê bao sử dụng Register-ObjectEvent

Đây là ví dụ được sửa đổi đôi chút từ PowerShell forums. Nó sẽ xuất dữ liệu từ lệnh ping không đồng bộ (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

Chỉ cần nhận xét nhanh. Đừng nghĩ đến việc gọi 'WaitForExit' trong quá trình, bởi vì sau đó không có đầu ra nào được tạo cho đến khi quá trình kết thúc. –

Các vấn đề liên quan