RoscoeT Posted July 27, 2017 Share Posted July 27, 2017 (edited) 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 July 27, 2017 by RoscoeT Link to comment Share on other sites More sharing options...
RoscoeT Posted July 27, 2017 Author Share Posted July 27, 2017 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 More sharing options...
Shrapnel Posted July 27, 2017 Share Posted July 27, 2017 Not sure if this will help you or not, but i use this function: expandcollapse popup; 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 More sharing options...
Trong Posted July 28, 2017 Share Posted July 28, 2017 Maybe stream cmd callback: expandcollapse popupLocal $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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now