RoscoeT Posted July 27, 2017 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
RoscoeT Posted July 27, 2017 Author 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?
Shrapnel Posted July 27, 2017 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
Trong Posted July 28, 2017 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,
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