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?

1 ответ

Есть ли способ в PowerShell, я могу потоковое содержимое вывода и ошибки во время процесса? В чистом.NET мы можем подписаться на события класса Process, могу ли я сделать то же самое в PowerShell?

Что вы можете! Что вам нужно, это объект события:

Событие объекта - это объект.Net, который не только имеет обычные свойства и методы в объекте, но также имеет другого члена с именем Event, на который можно зарегистрировать подписку, используя Register-ObjectEvent.

Вот слегка измененный пример с форумов PowerShell. Он будет выводить данные из команды ping асинхронно ( по крайней мере, с точки зрения сценария):

# 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 $_}
Другие вопросы по тегам