Jump to content

Stdout of console to vaiable but also show in console?


Recommended Posts

Hello all,

The issue i have is that when I use the run function with the flag $STDOUT_CHILD it seems to steal the output from the cmd window. And console write displays it only in the scite editor console.

I'm writing a function to run a console program and monitor its output for a certain condition.

The console program runs indefinitely until its stopped, so I am checking each line of stdout by passing it to a callback function rather than putting all stdout into a string.(in my example ping.exe and ConsoleWrite).

I'm not sure what I'm doing wrong here. Is there a way to read stdout of a console application in a cmd window without having it hijacked?

 

Local $CMD = "ping -n 10 10.0.2.2"

_GetDOS_Stream_Output($CMD, "ConsoleWrite", "My Window")

Func _GetDOS_Stream_Output($sCommand, $sCallBackFunction = "ConsoleWrite", $sTitle = False) ; for each line of stdout call a callback function. Default is ConsoleWrite. Optional Window Title.
    Local $iPID, $sOutput = "", $sWinTitle = ""
    If $sTitle Then $sWinTitle = "title " & $sTitle & "|" ; set the window title.
    $iPID = Run('"' & @ComSpec & '" /c ' & $sWinTitle & $sCommand, "",  @SW_MAXIMIZE, $STDERR_CHILD + $STDOUT_CHILD)
    While 1
        $sOutput = StdoutRead($iPID, False, False)
        If @error Then
            ExitLoop
        EndIf

        If @extended Then ; @extended contains number bytes captured from stdout
            Call($sCallBackFunction, $sOutput);
        EndIf
        Sleep(100)
    WEnd
    Return $iPID
EndFunc   ;==>_GetDOS_Stream_Output

 

I see someone else having this issue here:

'

 

Edited by RoscoeT
Link to comment
Share on other sites

It seems that I have a bit of an answer. It looks like ConsoleWrite only outputs to a dos window if you compile the script and set the CUI option.

https://www.autoitscript.com/autoit3/docs/functions/ConsoleWrite.htm

So new questions.

- Is there an other way to to write to dos window?

or

- Is there another way to read from a dos window without hijacking the stdout?

 

 

Link to comment
Share on other sites

Not sure if this will help you or not, but i use this function:

 

; Function Name _RunReadStd()
; ==================================================================================================
;
; Function Name:   _RunReadStd()
; Description::    Run a specified command, and return the Exitcode, StdOut text and
;                  StdErr text from from it. StdOut and StdErr are @tab delimited,
;                  with blank lines removed.
; Parameter(s):    $doscmd: the actual command to run, same as used with Run command
;                  $timeoutSeconds: maximum execution time in seconds, optional, default: 0 (wait forever),
;                  $workingdir: directory in which to execute $doscmd, optional, default: @ScriptDir
;                  $flag: show/hide flag, optional, default: @SW_HIDE
;                  $sDelim: stdOut and stdErr output deliminter, optional, default: @TAB
;                  $nRetVal: return single item from function instead of array, optional, default: -1 (return array)
; Requirement(s):  AutoIt 3.2.10.0
; Return Value(s): An array with three values, Exit Code, StdOut and StdErr
; Author(s):       lod3n
;                  (Thanks to mrRevoked for delimiter choice and non array return selection)
;                  (Thanks to mHZ for _ProcessOpenHandle() and _ProcessGetExitCode())
;                  (MetaThanks to DaveF for posting these DllCalls in Support Forum)
;                  (MetaThanks to JPM for including CloseHandle as needed)
;
; ==================================================================================================
Func _RunReadStd($doscmd, $timeoutSeconds = 0, $workingdir = @ScriptDir, $flag = @SW_HIDE, $nRetVal = -1, $sDelim = @TAB)

    Local $aReturn, $i_Pid, $h_Process, $i_ExitCode, $sStdOut, $sStdErr, $runTimer
    Dim $aReturn[3]

    ; run process with StdErr and StdOut flags
    $runTimer = TimerInit()
    $i_Pid = Run(@ComSpec & " /c " & $doscmd, $workingdir, $flag, 6) ; 6 = $STDERR_CHILD+$STDOUT_CHILD

    ; Get process handle
    Sleep(100) ; or DllCall may fail - experimental
    $h_Process = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $i_Pid)

    ; create tab delimited string containing StdOut text from process
    $aReturn[1] = ""
    $sStdOut = ""
    While 1
        $sStdOut &= StdoutRead($i_Pid)
        If @error Then ExitLoop
    WEnd
    $sStdOut = StringReplace($sStdOut, @CR, @TAB)
    $sStdOut = StringReplace($sStdOut, @LF, @TAB)
    $aStdOut = StringSplit($sStdOut, @TAB, 1)
    For $i = 1 To $aStdOut[0]
        $aStdOut[$i] = StringStripWS($aStdOut[$i], 3)
        If StringLen($aStdOut[$i]) > 0 Then
            $aReturn[1] &= $aStdOut[$i] & $sDelim
        EndIf
    Next
    $aReturn[1] = StringTrimRight($aReturn[1], 1)

    ; create tab delimited string containing StdErr text from process
    $aReturn[2] = ""
    $sStdErr = ""
    While 1
        $sStdErr &= StderrRead($i_Pid)
        If @error Then ExitLoop
    WEnd
    $sStdErr = StringReplace($sStdErr, @CR, @TAB)
    $sStdErr = StringReplace($sStdErr, @LF, @TAB)
    $aStderr = StringSplit($sStdErr, @TAB, 1)
    For $i = 1 To $aStderr[0]
        $aStderr[$i] = StringStripWS($aStderr[$i], 3)
        If StringLen($aStderr[$i]) > 0 Then
            $aReturn[2] &= $aStderr[$i] & $sDelim
        EndIf
    Next
    $aReturn[2] = StringTrimRight($aReturn[2], 1)

    ; kill the process if it exceeds $timeoutSeconds
    If $timeoutSeconds > 0 Then
        If TimerDiff($runTimer) / 1000 > $timeoutSeconds Then
            ProcessClose($i_Pid)
        EndIf
    EndIf

    ; fetch exit code and close process handle
    If IsArray($h_Process) Then
        Sleep(100) ; or DllCall may fail - experimental
        $i_ExitCode = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $h_Process[0], 'int*', 0)
        If IsArray($i_ExitCode) Then
            $aReturn[0] = $i_ExitCode[2]
        Else
            $aReturn[0] = -1
        EndIf
        Sleep(100) ; or DllCall may fail - experimental
        DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $h_Process[0])
    Else
        $aReturn[0] = -2
    EndIf

    ; return single item if correctly specified with with $nRetVal
    If $nRetVal <> -1 And $nRetVal >= 0 And $nRetVal <= 2 Then Return $aReturn[$nRetVal]

    ; return array with exit code, stdout, and stderr
    Return $aReturn

EndFunc   ;==>_RunReadStd

 

Link to comment
Share on other sites

Maybe stream cmd callback:

Local $iCommand = "ping -n 10 10.0.2.2"
_StreamCMD($iCommand)
;~ MsgBox(0, "", _StreamCMD($iCommand))


Func _StreamCMD($sCMD, $sCallBackFunction = Default, $WorkingDir = Default, $iStreamType = Default, $iShowFlag = Default, $iDelay = Default)
    If StringStripWS($sCMD, 8) = "" Then Return ""
    If $sCallBackFunction = Default Then $sCallBackFunction = "ConsoleWrite"
    If $WorkingDir = Default Then $WorkingDir = @SystemDir ;@WindowsDir & '\System32'
    If $iStreamType = Default Then $iStreamType = $STDERR_CHILD + $STDOUT_CHILD
    If $iShowFlag = Default Then $iShowFlag = False
    If $iDelay = Default Then $iDelay = 250
    ConsoleWrite("! Execute: " & $sCMD & @CRLF)
;~  Local $sTMP = '', $sSTD = '', $sCOM = '"' & @WindowsDir & '\System32\cmd.exe"' & ' /c ' & $sCMD
    Local $sTMP = '', $sSTD = '', $sCOM = @ComSpec & ' /c ' & $sCMD
    Local $iWin = $iShowFlag ? @SW_SHOW : @SW_HIDE
    Local $iPID = Run($sCOM, $WorkingDir, $iWin, $iStreamType)
    While 1
        $sTMP = StdoutRead($iPID, False, False)
        If @error Then ExitLoop
        If $sTMP <> "" Then
            $sTMP = StringReplace($sTMP, @CR & @CR, '')
            $sSTD &= $sTMP
            Call($sCallBackFunction,$sTMP)
;~          ConsoleWrite($sTMP)
            Sleep($iDelay)
        EndIf
    WEnd
    While 1
        $sTMP = StderrRead($iPID, False, False)
        If @error Then ExitLoop
        If $sTMP <> "" Then
            $sTMP = StringReplace($sTMP, @CR & @CR, '')
            $sSTD &= $sTMP
            Call($sCallBackFunction,$sTMP)
;~          ConsoleWrite($sTMP)
            Sleep($iDelay)
        EndIf
    WEnd
;~  If $sSTD <> "" Then ConsoleWrite(@CRLF)
    Return SetError(@error, @extended, $sSTD)
EndFunc   ;==>_StreamCMD
; * -----:|  Dao Van Trong - TRONG.WIN

 

Regards,
 

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...