events - How to capture process output asynchronously in powershell? -
i want capture stdout , stderr process start in powershell script , display asynchronously console. i've found documentation on doing through msdn , other blogs.
after creating , running illustration below, can't seem output displayed asynchronously. of output displayed when process terminates.
$ps = new-object system.diagnostics.process $ps.startinfo.filename = "cmd.exe" $ps.startinfo.useshellexecute = $false $ps.startinfo.redirectstandardoutput = $true $ps.startinfo.arguments = "/c echo `"hi`" `& timeout 5" $action = { write-host $eventargs.data } register-objectevent -inputobject $ps -eventname outputdatareceived -action $action | out-null $ps.start() | out-null $ps.beginoutputreadline() $ps.waitforexit()
in example, expecting see output of "hi" on commandline before end of programme execution because outputdatareceived event should have been triggered.
i've tried using other executables - java.exe, git.exe, etc. of them have same effect, i'm left think there simple i'm not understanding or have missed. else needs done read stdout asynchronously?
unfortunately asynchronous reading not easy if want properly. if phone call waitforexit() without timeout utilize function wrote (based on c# code):
function invoke-executable { # runs specified executable , captures exit code, stdout # , stderr. # returns: custom object. param( [parameter(mandatory=$true)] [validatenotnullorempty()] [string]$sexefile, [parameter(mandatory=$false)] [string[]]$cargs, [parameter(mandatory=$false)] [string]$sverb ) # setting process invocation parameters. $opsi = new-object -typename system.diagnostics.processstartinfo $opsi.createnowindow = $true $opsi.useshellexecute = $false $opsi.redirectstandardoutput = $true $opsi.redirectstandarderror = $true $opsi.filename = $sexefile if (! [string]::isnullorempty($cargs)) { $opsi.arguments = $cargs } if (! [string]::isnullorempty($sverb)) { $opsi.verb = $sverb } # creating process object. $oprocess = new-object -typename system.diagnostics.process $oprocess.startinfo = $opsi # creating string builders store stdout , stderr. $ostdoutbuilder = new-object -typename system.text.stringbuilder $ostderrbuilder = new-object -typename system.text.stringbuilder # adding event handers stdout , stderr. $sscripblock = { if (! [string]::isnullorempty($eventargs.data)) { $event.messagedata.appendline($eventargs.data) } } $ostdoutevent = register-objectevent -inputobject $oprocess ` -action $sscripblock -eventname 'outputdatareceived' ` -messagedata $ostdoutbuilder $ostderrevent = register-objectevent -inputobject $oprocess ` -action $sscripblock -eventname 'errordatareceived' ` -messagedata $ostderrbuilder # starting process. [void]$oprocess.start() $oprocess.beginoutputreadline() $oprocess.beginerrorreadline() [void]$oprocess.waitforexit() # unregistering events retrieve process output. unregister-event -sourceidentifier $ostdoutevent.name unregister-event -sourceidentifier $ostderrevent.name $oresult = new-object -typename psobject -property ([ordered]@{ "exefile" = $sexefile; "args" = $cargs -join " "; "exitcode" = $oprocess.exitcode; "stdout" = $ostdoutbuilder.tostring().trim(); "stderr" = $ostderrbuilder.tostring().trim() }) homecoming $oresult }
it captures stdout, stderr , exit code. illustration usage:
$oresult = invoke-executable -sexefilename 'ping.exe' -cargs @('8.8.8.8', '-a') $oresult | format-list -force
for more info , alternative implementations (in c#) read this blog post.
events powershell asynchronous
No comments:
Post a Comment