Sign in to follow this  
Followers 0
blademonkey

GUI version of Tail

25 posts in this topic

#1 ·  Posted (edited)

Hey all,

long time no post. I have create a mess of an application. The code is quite sloppy (which is starting to be a bad habit), but that's not the point.

here's the background on this file:

I wanted to create A gui version of the Unix command tool TAIL.

for those of you who are not familiar with tail, it's an app that will list the last lines of a file. the cool part is that you can set it to loop so if the file gets edited from any other process, you will see it in your command window. It's pretty slick.

what i did:

Created a bastard of a program that does not seem to close once you initiate the Tail button.

the trick is that the button calls a function that has a While 1 loop. so in total I have two while loops, but i do not know how to trap exit codes in the second one. I would appreciate if someone could explain to me how I can create an event that applies globally to the entire App.

I will post the code along with an attached dummyfile generator I scaped together (in case you dont have a file to tail).

Disclaimer: I am fully aware that there are ports of Tail to windows, i have several in addition to some really great hybrids of Grep. Again, this is not the point, I am trying to understant the logic in tail as well as understand the GUI semantics of AUTOIT better.

; ----------------------------------------------------------------------------
;
; AutoIt Version: Beta v3.1.1.133 
; Author:        Lawrence Scott
; Date:         08/02/2006
;
; Script Function:
;   This program is a GUI version of the Unix Tail utility.
;
; ----------------------------------------------------------------------------

;-----------------------------------------------
;           Script Environment settings         |
;-----------------------------------------------
#include <File.au3>
#include <GUIConstants.au3>
#Include <GuiEdit.au3>
Opt("GUIOnEventMode", 1)



;----------------------------------------
;           Script Main body            |
;----------------------------------------


;             Start GUI Window and Elements creation -->
$W_size_l = 700
$Wsize_h =400
$mainWindow = GUICreate("Tails",$W_size_l,$Wsize_h) ;Creates main Window
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")             
GUISetState(@SW_SHOW)

GUICtrlCreateLabel("Please select the file you want to tail", 30, 10)  

$fileopenButton = GUICtrlCreateButton("Open File",30, 40)
GUICtrlSetOnEvent($fileopenButton, "FileopenButton")

$TailButton = GUICtrlCreateButton("Tail it",200, 40)
GUICtrlSetOnEvent($TailButton, "Tailit")

                                                                            
$editControl = GUICtrlCreateEdit("",30,120, $W_size_l-60,   ($Wsize_h/3)*2,$WS_VSCROLL+ _ 
                                                             $ES_MULTILINE+$ES_AUTOVSCROLL+$ES_READONLY)
$LabelControl = GUICtrlCreateinput("Chosen file",30,80, 300, 20 )
$linecountcontrol = GUICtrlCreateInput("Lines : ",360,80,150,20,$ES_READONLY)
$loopQAcontrol = GUICtrlCreateInput("Loop : ",360,40,150,20,$ES_READONLY)

;         <-- End GUI Window and Elements creation 


;           Start Main While loop -->
while 1
sleep(1)
WEnd
;           <-- End Main While loop 

;---------------------------------------------------
;               Functions Declarations              |
;---------------------------------------------------

;--------------------
;  Function Tailit() |
;----------------------------------------------------------------------------------------------------
;  Main Function that will actually keep checking the target file for any changes
;  via a second While loop
func Tailit()

;           Function Environment settings   -->

    $error =0
    $loopcount = 0
    $file = ControlGetText("Tails","",$LabelControl)
    if not fileexists($file) Then
        $error = -1
        EndIf
    $openfile = FileOpen($file,0)
    
    $count = _FileCountLines($file)
    $scan= filereadline($file, $count)
    
    $file_contents = ""
    for $x =1 to $count
        $file_contents = $file_contents  & filereadline($file, $x)& @CRLF
    next
    GUICtrlSetData($editControl, $file_contents)
    GUICTrlSetData($linecountcontrol, "Lines : " &$count)
    _GUICtrlEditLineScroll ($editControl, 0, $count)
;           <<- Function Environment settings   

;           Start While loop -->
;           This is where are the processing happens.
    while 2
        $loopcount = $loopcount +1
    GUICTrlSetData($loopQAcontrol, "Loop in : " &$loopcount)
        
    $recount = _FileCountLines($file)
    $rescan = filereadline($file, $recount)
 
;               Start Select Block -->
    Select
    case $error = -1 
        MsgBox(0,"Error","no valid file specified, please open a file first")
        ExitLoop        
    case $rescan <> $scan
            $file_contents = ""     
            for $x =1 to $count
                $file_contents = $file_contents  & filereadline($file, $x)& @CRLF
            next
            GUICtrlSetData($editControl, $file_contents)
            GUICTrlSetData($linecountcontrol, "Lines : " &$count)
            _GUICtrlEditLineScroll ($editControl, 0, $recount)
            
            $scan = $rescan
            
    case $recount <> $count
            if $recount > $count then
                $file_contents = ""     
                for $x =1 to $recount
                    $file_contents = $file_contents  & filereadline($file, $x)& @CRLF
                next
                GUICtrlSetData($editControl, $file_contents)
                GUICTrlSetData($linecountcontrol, "Lines : " &$recount)
                _GUICtrlEditLineScroll ($editControl, 0, $recount)
                
                $count = $recount
            elseif $recount < $count Then
                
                $file_contents = ""
                for $x =1 to $recount
                    $file_contents = $file_contents  & filereadline($file, $x)& @CRLF
                next
                GUICtrlSetData($editControl, $file_contents)
                GUICTrlSetData($linecountcontrol, "Lines : " &$recount)
                _GUICtrlEditLineScroll ($editControl, 0, $recount)
                $linecountcontrol = GUICtrlCreateInput("Lines : " &$recount,360,80,150,40,$ES_READONLY)
                $count = $recount
            endif
        
    EndSelect
;               <-- End Select Block
    WEnd
;           <-- End while Loop  
    
    fileclose($openfile)
EndFunc 
;----------------------------------------------------------------------------------------------------
;  End Function Tailit()  |
;-------------------------

;----------------------------
;  Function FileopenButton() |
;----------------------------------------------------------------------------------------------------
;  Creates Open File dialog Box, sets the select as the target file to be Tailed
func FileopenButton()
$selected_file = FileOpenDialog("Open",@ScriptDir,"Text Files (*.*)")
GUICtrlSetData($LabelControl, $selected_file)
EndFunc
;----------------------------------------------------------------------------------------------------
;  End Function FileopenButton() |
;--------------------------------

Func CLOSEClicked()
  Exit
EndFunc

Ya i know, it's REAL ugly, please bare with my code. Oh yea, it's Beta, so dont post the errors from a non-beta compile (those posts tend to spam my threads).

Thanks to whoever takes the time to look through it.

-Blademonkey

Edit: Updated Code and Attachment. :whistle:

dummyfile.au3

tail.au3

Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

Lots of text here, but i think what you mean is this:

While 1
     While $i
       If $Exit Then ExitLoop 2
    Wend
Wend
that didnt really work. I actually just cut and pasted your code into my second while loop and it bombed saying it didnt know what $exit was.

I did try adding this:

if $GUI_EVENT_CLOSE Then 
        Exitloop
    endif

which sorta worked but it wouldnt go through the whole loop.

I think it's related to my script being set on EventMode, not "MessagePolling" Mode.

Anyone ? Anyone? Bueler? Bueler?

I have updated my code since then (took out the test function).

I'll update the post with the new code.

Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

I was jsut looking over the code, would this be an easy implementation of tail. Uses _FileReadToArray() rather than reading a file line by line and adding to one long string.

_Tail:

Func _Tail( $i_numTail, $a_readLines )
    #calculate which line to end on
    $endLine = UBound( $a_readLines ) - $i_numTail
    
    Dim $a_tailLines[ $i_numTail ]
        
    For $iter = UBound( $a_readLines ) - 1 To $endLine Step -1
        $a_tailLines[ $iter - $endLine ] = $a_readLines[ $iter ]
    Next
    
    Return $a_tailLines        
EndFunc
oÝ÷ ÙKá1jjey«­¢+Ø(¥¹±Õ±Ðí¥±¹ÔÌÐì(¥¹±Õ±ÐíÉÉä¹ÔÌÐì((ÀÌØíÍ}¥±9µôÅÕ½ÐíÑÍйÑáÐÅÕ½Ðì)¥´ÀÌØí}1¥¹Ì)}¥±IQ½ÉÉä ÀÌØíÍ}¥±9µ°ÀÌØí}1¥¹Ì¤((ÀÌØí¥}Ñ¥±1¥¹ÌôÔ((ÀÌØí}Q¥°ô}Q¥° ÀÌØí¥}Ñ¥±1¥¹Ì°ÀÌØí}1¥¹Ì¤()}ÉÉå¥ÍÁ±ä ÀÌØí}Q¥°°ÅÕ½ÐìÅÕ½Ðì¤

Sample Input file( test.txt ):

1
2
3
4
5
6
7
8
9
10

WARNING: No error checking is involved in my example here or in the _Tail function. Add it as needed.


_____________________________________________________"some people live for the rules, I live for exceptions"Wallpaper Changer - Easily Change Your Windows Wallpaper

Share this post


Link to post
Share on other sites

I was jsut looking over the code, would this be an easy implementation of tail. Uses _FileReadToArray() rather than reading a file line by line and adding to one long string.

_Tail:

Func _Tail( $i_numTail, $a_readLines )
    #calculate which line to end on
    $endLine = UBound( $a_readLines ) - $i_numTail
    
    Dim $a_tailLines[ $i_numTail ]
        
    For $iter = UBound( $a_readLines ) - 1 To $endLine Step -1
        $a_tailLines[ $iter - $endLine ] = $a_readLines[ $iter ]
    Next
    
    Return $a_tailLines        
EndFunc
oÝ÷ ÙKá1jjey«­¢+Ø(¥¹±Õ±Ðí¥±¹ÔÌÐì(¥¹±Õ±ÐíÉÉä¹ÔÌÐì((ÀÌØíÍ}¥±9µôÅÕ½ÐíÑÍйÑáÐÅÕ½Ðì)¥´ÀÌØí}1¥¹Ì)}¥±IQ½ÉÉä ÀÌØíÍ}¥±9µ°ÀÌØí}1¥¹Ì¤((ÀÌØí¥}Ñ¥±1¥¹ÌôÔ((ÀÌØí}Q¥°ô}Q¥° ÀÌØí¥}Ñ¥±1¥¹Ì°ÀÌØí}1¥¹Ì¤()}ÉÉå¥ÍÁ±ä ÀÌØí}Q¥°°ÅÕ½ÐìÅÕ½Ðì¤

Sample Input file( test.txt ):

1
2
3
4
5
6
7
8
9
10

WARNING: No error checking is involved in my example here or in the _Tail function. Add it as needed.

Thanks, I just updated my massive code with some comments.

I do like the filetoarray function but it tends to slow down when you use on large log files.

Also, do you know what the limit on Array elements in Autoit is?

I work with logs that have 400+ elements.


---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

MsgBox(0, '', _Tail(@DesktopDir & '\Test.txt', 5))

Func _Tail($hFile, $i_ReturnLines)
    Local $sRead = FileRead($hFile), $aFile = StringSplit($sRead, @LF), $sHoldValue
    For $iCount = (($aFile[0] + 1) - $i_ReturnLines) To $aFile[0]
        $sHoldValue &= $aFile[$iCount] & @LF
    Next
    Return StringTrimRight($sHoldValue, 2)
EndFunc


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

I think the limit for an array is 16777215, definitely much higher than the 400+ you might need for the log files you must Tail().


_____________________________________________________"some people live for the rules, I live for exceptions"Wallpaper Changer - Easily Change Your Windows Wallpaper

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Well I rewrote the Tail Function using an array but it still does not solve my problem.

how do I break out of the second while loop?

thanks

-Blademonkey

Updated code

Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

Why is it even in a loop? What does $x represent? Your not returning an array, your returning a string (from tail(), (mines faster btw)). Your code isn't even debugable (GUICtrlSetDate($something, ????)). I remember you coding much nicer than this :whistle:


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

From a design standpoint, you're using "While 1" and "While 2" (Always true) and having issues trying to break out.

Why not use meaningful conditions, for example, "While $LinesRemaining < 10" or "While $Count > 0"?


[font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font]

Share this post


Link to post
Share on other sites

From a design standpoint, you're using "While 1" and "While 2" (Always true) and having issues trying to break out.

Why not use meaningful conditions, for example, "While $LinesRemaining < 10" or "While $Count > 0"?

Partly because I want the app to keep running until specific Controls are pressed ($GUI_EVENT_Close, or the End button). I want the app to continuously monitor the target file and show (realtime) the changes to it.

I'm not sure how to trigger an event in the second while loop.

I tried

while not $GUI_EVENT_CLOSE
sleep(100)
Wend

but it would not process anything in the while loop. So I am stuck, either I can get it to exit, but it does not continuously loop, or I get it to continuously loop and I have to exit through the Autoit Icon in the notification area(FKA Systray) or the process list.


---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

Right, you aren't going to answer my questions?


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Why is it even in a loop? What does $x represent? Your not returning an array, your returning a string (from tail(), (mines faster btw)). Your code isn't even debugable (GUICtrlSetDate($something, ????)). I remember you coding much nicer than this :whistle:

well it's in a loop because i want it to repeat semi-infinitely.

$x is a loop counter to demonstrate whether or not the loop is cycling.

I saw that I hashed up the code before i uploaded it so i updated it on the previous post, but here it is:

#include <File.au3>
#include <GUIConstants.au3>
#Include <GuiEdit.au3>


Opt("GUIOnEventMode", 1)
$W_size_l = 700
$Wsize_h =400
$mainWindow = GUICreate("Tails",$W_size_l,$Wsize_h) ;Creates main Window
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")             
GUISetState(@SW_SHOW)

GUICtrlCreateLabel("Please select the file you want to tail", 30, 10)  

$fileopenButton = GUICtrlCreateButton("Open File",30, 40)
GUICtrlSetOnEvent($fileopenButton, "FileopenButton")

$TailButton = GUICtrlCreateButton("Tail",200, 40)
GUICtrlSetOnEvent($TailButton, "_TailLoop")

$editControl = GUICtrlCreateEdit("",30,120, $W_size_l-60,   ($Wsize_h/3)*2,$WS_VSCROLL+$ES_MULTILINE+$ES_AUTOVSCROLL+$ES_READONLY)
$LabelControl = GUICtrlCreateinput("Chosen file",30,80, 300, 20 )
$linecountcontrol = GUICtrlCreateInput("Lines : ",360,80,150,20,$ES_READONLY)
$loopQAcontrol = GUICtrlCreateInput("Loop : ",360,40,150,20,$ES_READONLY)


while 1
Sleep(10)
WEnd



func FileopenButton()
$selected_file = FileOpenDialog("Open",@ScriptDir,"Text Files (*.*)")
GUICtrlSetData($LabelControl, $selected_file)
EndFunc

Func _TailLoop()
    local $x = 0
    $TailButton = GUICtrlCreateButton("end",250, 40)
    GUICtrlSetOnEvent($TailButton, "_Tailend")
    while 1
    $x = $x +1  
   $results = _Tail("test.txt")
   GUICtrlSetData($editControl, $results)
   GUICtrlSetData($loopQAcontrol, $x )
   sleep(100)
    WEnd
EndFunc

Func _Tail($hFile)
    dim $aFile
    local $string = ""
    _FileReadToArray($hFile,$aFile)
    for $i = 1 to UBound($aFile) -1
        $string = $string & $aFile[$i] & @CRLF
    next
    Return $string
EndFunc

Func _Tailend()
MsgBox(0,"Trap", "Tailend clicked!")
EndFunc

Func CLOSEClicked()
  Exit
EndFunc

and the comment about my code not being as good as you remember it: ouch. All I can say is that im focusing on breaking out of the second loop. I have already rewrite my original ugly function into somethin less ugly thanks to you and other people's help. I'm trying to get it to work and optimize the code, so bare with me.

PS: didnt see your question till after i replied to Skruge, sorry.

Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

Try this:

Func _TailLoop()
    Local $x = 0
    $TailButton = GUICtrlCreateButton("end",250, 40)
    GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
    GUICtrlSetOnEvent($TailButton, "_Tailend")
    GUISetState()
    While 1
        $x = $x +1
        $results = _Tail("test.txt")
        GUICtrlSetData($editControl, $results)
        GUICtrlSetData($loopQAcontrol, $x )
        Sleep(10)
    WEnd
EndFunc


[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

Try this:

Func _TailLoop()
    Local $x = 0
    $TailButton = GUICtrlCreateButton("end",250, 40)
    GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
    GUICtrlSetOnEvent($TailButton, "_Tailend")
    GUISetState()
    While 1
        $x = $x +1
        $results = _Tail("test.txt")
        GUICtrlSetData($editControl, $results)
        GUICtrlSetData($loopQAcontrol, $x )
        Sleep(10)
    WEnd
EndFunc
Same results as before.

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

Same results as before.

:whistle: Derr me... You are calling another function 10 million times in that loop. I had commented out the function call when I was looking at it.

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

:whistle: Derr me... You are calling another function 10 million times in that loop. I had commented out the function call when I was looking at it.

yes, that was my point. I am calling it everytime so that it runs and queries the contents of the file. I want it to show the changes made to the file realtime.


---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

Here's a go of what he means;

Randall

thanks, that's sort of works, but it does not loop. I want it to loop almost infinitely until interrupted by an event. That way it will keep checking the file for new lines, or modifications to the file.

As it is, your code only works when you click on tail.

What im looking for is for the Tail function to be a continuous loop until interrupted.

I thank you both for you efforts, but this is still short of my goal.

-Blademonkey


---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Share this post


Link to post
Share on other sites

Try this, this works for me, continously generating tail until i click the button to stop.

#include <File.au3>
#include <Array.au3>
#include <GUIConstants.au3>

$s_FileName = "test.txt"
Dim $a_Lines
Dim $read = True

GUICreate( "Tail Function - Continuous File Monitoring", 200, 200 )
$stop = GUICtrlCreateButton( "Click here to end file monitoring.", 10, 10, 180, 180, "0x0700" )
GUISetState( @SW_SHOW )

While $read = True    
    _FileReadToArray( $s_FileName, $a_Lines )

    $i_tailLines = 5

    $a_Tail = _Tail( $i_tailLines, $a_Lines )

#    _ArrayDisplay( $a_Tail, "" )
    
    $msg = GUIGetMsg()
    
    If $msg = $GUI_EVENT_CLOSE Or $msg = $stop Then
        $read = False
    EndIf
WEnd

Func _Tail( $i_numTail, $a_readLines )
    #calculate which line to end on
    $endLine = UBound( $a_readLines ) - $i_numTail
    
    Dim $a_tailLines[ $i_numTail ]
        
    For $iter = UBound( $a_readLines ) - 1 To $endLine Step -1
        $a_tailLines[ $iter - $endLine ] = $a_readLines[ $iter ]
    Next
    
    Return $a_tailLines        
EndFunc

Hope this helps.


_____________________________________________________"some people live for the rules, I live for exceptions"Wallpaper Changer - Easily Change Your Windows Wallpaper

Share this post


Link to post
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
Sign in to follow this  
Followers 0