Jump to content

_RunWaitGet() - StdOut and StdErr stream capture


 Share

Recommended Posts

Someone told me I should post this in the examples section.  I wrote this to make it easy for me to call a Windows console application and get its output using a single line of AutoIt code.  I hope it's helpful to someone else.

 

#include <Constants.au3>

; Examples:
MsgBox(0,"Windows Version",_RunWaitGet(@ComSpec & " /c ver",1,"",@SW_HIDE))
MsgBox(0,"System Info",_RunWaitGet(@SystemDir & "\systeminfo.exe",1))

; #FUNCTION# ====================================================================================================================
; Name ..........: _RunWaitGet

; Description ...: Runs the specified process, waits for it to exit, then returns the contents of its StdOut and/or StdErr streams.
;                  Handy for running command-line tools and getting their output.
; Syntax ........: _RunWaitGet($sProgram, $nOptions, $sWorkingDir, $nShowFlag)
; Parameters ....: $sProgram            - The full path of the program (EXE, BAT, COM, or PIF) to run
;                  $nOptions            - Add options together:
;                                            1 = Capture the StdOut stream.
;                                            2 = Capture the StdErr stream.
;                                            4 = Return when the stream(s) close(s), not when the process ends.
;                  $sWorkingDir         - The working directory. Blank ("") uses the current working directory.
;                                         This is not the path to the program.
;                  $nShowFlag           - The "show" flag of the executed program:
;                                            @SW_SHOW = Show window (default)
;                                            @SW_HIDE = Hidden window (or Default keyword)
;                                            @SW_MINIMIZE = Minimized window
;                                            @SW_MAXIMIZE = Maximized window
; Return values .: String value containing the captured contents.
;                  If there was a problem running the process, @error is set to the @error value returned by Run().
;                  Otherwise, @error is 0.
; Author ........: ToasterKing

; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: MsgBox(0,"System Info",_RunWaitGet(@SystemDir & "\systeminfo.exe",1))
;                  MsgBox(0,"Windows Version",_RunWaitGet(@ComSpec & " /c ver",1,"",@SW_HIDE))
; ===============================================================================================================================
Func _RunWaitGet($sProgram,$nOptions = 0,$sWorkingDir = @SystemDir,$nShowFlag = @SW_SHOW)
    Local $nRunOptFlags = 0,$sStreamOut = "" ; Initialize variables
    ; Determine flags for parent/child interaction
    If BitAND($nOptions,1) Then $nRunOptFlags += $STDOUT_CHILD
    If BitAND($nOptions,2) Then $nRunOptFlags += $STDERR_CHILD
    Local $hRunStream = Run($sProgram,$sWorkingDir,$nShowFlag,$nRunOptFlags) ; Run the process
    If @error Then Return SetError(@error,@extended,0) ; If there was an error code, return it.  Otherwise...
    While 1 ; Loop until the end of the stream, which indicates that the process has closed it (which usually means the process ended)
        If BitAND($nOptions,1) Then ; If user specified to capture STDOUT stream...
            $sStreamOut &= StdoutRead($hRunStream) ; Append new stream contents to existing variable while removing those contents from the stream.
            If @error = 2 And BitAND($nOptions,4) Then ExitLoop ; If stream ended and user specified to return when the stream closes, stop looping.
        EndIf
        If BitAND($nOptions,2) Then ; If user specified to capture STDERR stream...
            $sStreamOut &= StderrRead($hRunStream) ; Append new stream contents to existing variable while removing those contents from the stream.
            If @error = 2 And BitAND($nOptions,4) Then ExitLoop ; If stream ended and user specified to return when the stream closes, stop looping.
        EndIf
        If Not BitAND($nOptions,4) And Not ProcessExists($hRunStream) Then ExitLoop ; If using the default setting and the process ended, stop looping.
        Sleep(100) ; To avoid overloading the CPU
    WEnd
    Return SetError(0,0,$sStreamOut) ; Return the captured contents and @error = 0
EndFunc

 

Link to comment
Share on other sites

That's not the sort of use I intended when I wrote the function, but this is AutoIt.  Of course there is a way.™

Try my scribblings below.  If you want something wrapped up in a nice, tidy function, that's an exercise for the reader.  :)

#include <Constants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiEdit.au3>
$FormMain = GUICreate("Crappy Demo", 602, 297)
$EditStdOut = GUICtrlCreateEdit("", 16, 16, 569, 225, BitOR($ES_AUTOVSCROLL,$ES_WANTRETURN,$WS_VSCROLL))
$ButtonTraceRoute = GUICtrlCreateButton("Trace Route!", 240, 256, 115, 25)
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $ButtonTraceRoute
            _TraceRoute()
    EndSwitch
WEnd

Func _TraceRoute()
    GUICtrlSetState($ButtonTraceRoute,$GUI_DISABLE)
    $hRunStream = Run(@SystemDir & "\tracert.exe www.autoitscript.com",@SystemDir,@SW_HIDE,$STDOUT_CHILD)
    While 1
        $sStreamOut = StdoutRead($hRunStream)
        If @error Then
            ExitLoop
        Else
            _GUICtrlEdit_AppendText($EditStdOut,$sStreamOut)
        EndIf
        Sleep(100)
    WEnd
    GUICtrlSetState($ButtonTraceRoute,$GUI_ENABLE)
EndFunc

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...