dabus Posted June 23, 2008 Share Posted June 23, 2008 (edited) Hi there,I want to have some sort of tail in a GUI.To accomplish this, I have created a little script.Here's a quick and dirty conversion of it.Note that you will have to press exit to close the app.SpecialEvents don't seem to work, but I don't care.As mentioned, this is a small part of another project.You may also replace the /c with a /k switch to work with cmd via the input-box.expandcollapse popup; *** Start added by AutoIt3Wrapper *** #include <Constants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> ; *** End added by AutoIt3Wrapper *** Global $tLog=@ScriptDir&'\log.txt', $POpen=1, $tLine='', $tOutput='', $Stream Global $pGui, $pButton1, $pButton2, $pButton3, $pEdit1, $pProgress1, $pInput1, $pLabel1, $pLabel2 _Process_Gui() _Process_Run(@ComSpec & ' /c dir '&@SystemDir, @ScriptDir) While $POpen Sleep(100) WEnd ; --------------------------------------------------------------------------------------------- ; Create a small gui that will be used to monitor the progess ; --------------------------------------------------------------------------------------------- Func _Process_Gui($a=0) AutoItSetOption('GUIOnEventMode', 1) $pGui = GUICreate('Test', 550, 410, 100) GUISetFont(8, 400, 0, "MS Sans Serif") GUICtrlSetOnEvent ($GUI_EVENT_CLOSE, '_Process_OnEvent') GUICtrlSetOnEvent ($GUI_EVENT_MINIMIZE, '_Process_OnEvent') GUICtrlSetOnEvent ($GUI_EVENT_RESTORE, '_Process_OnEvent') $pLabel1 = GUICtrlCreateLabel('Watch this', 35, 35, 380, 20) $pProgress1 = GUICtrlCreateProgress(35, 55, 480, 20) $pLabel2 = GUICtrlCreateLabel('', 35, 85, 380, 20) If $a=0 Then $pEdit1 = GUICtrlCreateEdit('', 35, 115, 480, 210, $ES_READONLY+$WS_HSCROLL) Else $pEdit1 = GUICtrlCreateEdit('', 35, 115, 480, 210, $ES_READONLY+$WS_HSCROLL+$WS_VSCROLL+$ES_AUTOVSCROLL) EndIf $pInput1 = GUICtrlCreateInput('', 35, 340, 154, 20) $pButton1 = GUICtrlCreateButton('Write STDIn', 198, 340, 154, 20) GUICtrlSetOnEvent ($pButton1, '_Process_OnEvent') $pButton2 = GUICtrlCreateButton('Log', 361, 340, 154, 20) GUICtrlSetOnEvent ($pButton2, '_Process_OnEvent') $pButton3 = GUICtrlCreateButton('Exit', 35, 370, 480, 20) GUICtrlSetOnEvent ($pButton3, '_Process_OnEvent') GUISetState(@SW_SHOW) EndFunc ; --------------------------------------------------------------------------------------------- ; On-Event functions for the _Process_Gui ; --------------------------------------------------------------------------------------------- Func _Process_OnEvent() Switch @GUI_CtrlId Case $GUI_EVENT_MINIMIZE GUISetState(@SW_MINIMIZE, $pGui) Case $GUI_EVENT_RESTORE GUISetState(@SW_RESTORE, $pGui) Case $GUI_EVENT_CLOSE Exit Case $pButton1 StdinWrite($Stream, GUICtrlRead($pInput1)&@CRLF) If @error = -1 Then $tOutput = $tOutput & @CRLF & 'That did not work.' $tOutput = StringRight($tOutput, StringLen($tOutput) - StringInStr($tOutput, @LF, 0, -14)) ControlSetText($pGui, '', $pEdit1, $tOutput) EndIf Case $pButton2; open log ShellExecute($tLog) Case $pButton3 $POpen=0 GUICtrlSetData($pLabel1, 'Please wait for the process to exit...'); set hint GUICtrlSetColor($pLabel1, '0xff0000'); paint the text red GUICtrlSetState($pInput1, $GUI_DISABLE) GUICtrlSetState($pButton1, $GUI_DISABLE) GUICtrlSetState($pButton2, $GUI_DISABLE) GUICtrlSetState($pButton3, $GUI_DISABLE) AutoItSetOption('GUIOnEventMode', 0) EndSwitch EndFunc ; --------------------------------------------------------------------------------------------- ; The Adlib_Function that is called by _Process_Run to write monitored output to log and update edit-control ; --------------------------------------------------------------------------------------------- Func _Process_AL_Run() ;$tLine = _Trans_Dos2Ascii($tLine) FileWrite($tLog, $tLine); write the log $tOutput = $tOutput & $tLine; append the new text $tOutput = StringRight($tOutput, StringLen($tOutput) - StringInStr($tOutput, @LF, 0, -14)); just get the last 14 lines ControlSetText($pGui, '', $pEdit1, $tOutput); set the text $tLine=''; reset the new input EndFunc ;==>_Process_AL_Run ; --------------------------------------------------------------------------------------------- ; Run a process and moitor it by using AdLib (here _Process_AL_Run ) ; --------------------------------------------------------------------------------------------- Func _Process_Run($a, $B); $a=program, $b=directory ;_PrintDebug('+' & @ScriptLineNumber & ' Calling _Process_Run') $stream = Run($a, $b, @SW_HIDE, $STDIN_CHILD + $STDERR_CHILD + $STDOUT_CHILD); run hidden with stdout/err-read If Not @error Then AdlibEnable ("_Process_AL_Run", 750) While 1 $line = StdoutRead($Stream); capture while getting stream If @error Then ExitLoop If $line Then $tLine = $tLine & $Line; capture while getting stream $line = StderrRead($Stream) If @error Then ExitLoop If $line Then $tLine = $tLine & $Line; capture while getting stream Sleep(10) WEnd AdlibDisable() _Process_AL_Run(); write the last additions Else $tOutput = $tOutput & @CRLF & 'Could not run command.' & @CRLF $tOutput = StringRight($tOutput, StringLen($tOutput) - StringInStr($tOutput, @LF, 0, -14)) ControlSetText($pGui, '', $pEdit1, $tOutput) EndIf EndFunc ExitAs you can see, I added a sleep to avoid a big cpu-usage. The other thing I use is a temporary variable to store the output and update the edit-control later (to avoid flickering and high cpu-usage). When using 7zip, I rarely don't get the last output 7zip creates / send to stdout. Seems to be 1 % of my attemps.Do I have another option than reducing the sleep to avoid that?The workaround I tried to use was some sort of tail.udf that read created log-files, but the size via FileGetSize of the log was not updated properly. I posted that hereI could watch the update with a regular tail, so the filesize had to increase, but it wouldn't do so instantly, but a few seconds later.The result was that the gui was not updated and it looked like the application hang.The last time I played with tail was with AutoIt 3.2.10 on a XP SP2 installation.Someone told me that the the filegetsize-"call" he saw in an old opensource-code may be a little bit buggy. -- No offense here! I don't even know if AutoIt uses these calls in later versions nor if is really true. --Do you know if there is another option to get the filesize with a dll-call or something?I'd be happy if you could give me an advice.Best RegardsDabus Edited June 23, 2008 by dabus Link to comment Share on other sites More sharing options...
dabus Posted June 23, 2008 Author Share Posted June 23, 2008 Bump. Nobody with simillar problems?!? Link to comment Share on other sites More sharing options...
Valik Posted June 23, 2008 Share Posted June 23, 2008 (edited) Your code is flawed. You shouldn't quit reading until both StdOutRead() and StdErrRead() set @error. As you have it written now, whichever stream ends first will end the loop even though there may be data on the other stream. So, in your 1% case, which is nothing more than a classic race condition, the child process ends right after StdOutRead() but right before StdErrRead(). The stderr stream is closed, StdErrRead() sees it can not get any more data, sets @error and your loop ends even though StdOutRead() has more data it can read.Edit: Also, for simplicity, you may wish to look at the merged flag for STDIO. Since you are concatenating both streams into the same buffer anyway, it would simplify the code. Edited June 23, 2008 by Valik Link to comment Share on other sites More sharing options...
DaveF Posted June 23, 2008 Share Posted June 23, 2008 Bah, beaten to the punch. Yes, what he said. Yes yes yes, there it was. Youth must go, ah yes. But youth is only being in a way like it might be an animal. No, it is not just being an animal so much as being like one of these malenky toys you viddy being sold in the streets, like little chellovecks made out of tin and with a spring inside and then a winding handle on the outside and you wind it up grrr grrr grrr and off it itties, like walking, O my brothers. But it itties in a straight line and bangs straight into things bang bang and it cannot help what it is doing. Being young is like being like one of these malenky machines. Link to comment Share on other sites More sharing options...
dabus Posted June 25, 2008 Author Share Posted June 25, 2008 Thank you. 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