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 $_}