Siva
Siva

Reputation: 302

Capture and display STDOUT at the same time

I have the following code to capture and process the Run command output. How do I modify it such that the Run command window displays output and at the same time the output gets logged? Replacing @SW_HIDE with @SW_SHOW (or the equivalent) just shows a blank command window.

Something similar to the linux tee command which logs to file while it prints STDOUT.

$CurrentPID = Run(@ComSpec & ' /c ' & $CurrentLogCmd, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

If Not ProcessWaitClose($CurrentPID,60) Then
    WriteLog("[Warning] Timed-out.Finding date in current hour raw log -" & $CurrentLogFileName)
    $F_LogWarningExist = 1
    Return $C_SUCCESS ; Take chances and proceed with parsing raw logs
EndIf

$CurrentOutput = StdoutRead($CurrentPID)

Upvotes: 6

Views: 19351

Answers (2)

user4157124
user4157124

Reputation: 3002

Something similar to the linux tee command which logs to file while it prints STDOUT.

Redirecting STDOUT makes receiving party (the script) responsible for display and logging. As per documentation:

StdoutRead() does not block, it will return immediately. In order to get all data, it must be called in a loop.

Example:

#AutoIt3Wrapper_Change2CUI=Y

#include <Constants.au3>
#include <MsgBoxConstants.au3>

Global Enum  $EXIT_OK, _
             $EXIT_NOCOMPILE, _
             $EXIT_ABORT

Global Const $g_sPromptError  = 'Compile this script and run resulting executable instead.', _
             $g_sPromptInput  = 'Enter a command:', _
             $g_sInputDefault = 'ping localhost -n 10'

Global       $g_sCMD = '', _
             $g_sSTD = ''

Main()

Func Main()

    If Not @Compiled Then

        MsgBox($MB_OK + $MB_ICONERROR, @ScriptName, $g_sPromptError)
        Exit $EXIT_NOCOMPILE

    EndIf

    $g_sCMD = InputBox(@ScriptName, $g_sPromptInput, $g_sInputDefault)
    If @error Then Exit $EXIT_ABORT

    $g_sSTD = _getCmdStd($g_sCMD)
    MsgBox($MB_OK + $MB_ICONINFORMATION, $g_sCMD, $g_sSTD)

    Exit $EXIT_OK
EndFunc

Func _getCmdStd(Const $sCMD, Const $sDir = '', Const $iType = $STDERR_MERGED, Const $bShow = False, Const $iDelay = 100)
    Local       $sTMP = ''
    Local       $sSTD = ''
    Local       $sCOM = @ComSpec & ' /c ' & $sCMD
    Local Const $iWin = $bShow ? @SW_SHOW : @SW_HIDE
    Local Const $iPID = Run($sCOM, $sDir, $iWin, $iType)

    While True

        $sTMP = StdoutRead($iPID, False, False)

        If @error Then

            ExitLoop 1

        ElseIf $sTMP Then

            $sTMP  = StringReplace($sTMP, @CR & @CR, '')
            $sSTD &= $sTMP

            ConsoleWrite($sTMP)

        EndIf

        Sleep($iDelay)

    WEnd

    Return SetError(@error, @extended, $sSTD)
EndFunc

Returns STDOUT (and STDERR) after execution completes, while writing to console during execution. Replace MsgBox() as required (logging function).

Upvotes: 2

Xenobiologist
Xenobiologist

Reputation: 2151

ConsoleWrite(_getDOSOutput('ipconfig /all') & @CRLF)

Func _getDOSOutput($command)
    Local $text = '', $Pid = Run('"' & @ComSpec & '" /c ' & $command, '', @SW_HIDE, 2 + 4)
    While 1
            $text &= StdoutRead($Pid, False, False)
            If @error Then ExitLoop
            Sleep(10)
    WEnd
    Return StringStripWS($text, 7)
EndFunc   ;==>_getDOSOutput

Maybe this helps you out.

Upvotes: 4

Related Questions