NickT Posted August 29, 2010 Share Posted August 29, 2010 (edited) I am new to AutoIt and could use some help with a script that I am writing. The problem that I keep getting is a recursion error. Here is the script: #NoTrayIcon Global $count=0 startup() Func startup() $count=$count+1 DriveMapDel("z:") Sleep(2000) If $count=7 Then Shutdown(22) ShellExecuteWait("startup.bat", "", "c:\windows\system", "", @SW_HIDE) DriveStatus("z:") If @error Then startup() $read=FileRead("c:\log\log.txt") FileWrite("z:\log.txt", $read & @CRLF) FileDelete("c:\log\log.txt") $count=0 pingtest() EndFunc Func pingtest() If $count=7 Then ShellExecuteWait("nopinglog.bat", "", "c:\windows\system", "", @SW_HIDE) ProcessClose("specified process") ProcessClose("specified process") ProcessClose("specified process") $count=0 Sleep(5000) startup() EndIf Ping("10.0.0.1", 15000) If @error Then $count=$count+1 Sleep(5000) pingtest() Else $count=0 Sleep(55000) time() EndIf EndFunc Func time() $time=@HOUR & ":" & @MIN & ":" & @SEC If $time >= "20:00:00" And $time <= "20:01:00" Then ShellExecuteWait("pinglog.bat", "", "c:\windows\system", "", @SW_HIDE) Sleep(60000) runcheck() Else runcheck() EndIf EndFunc Func runcheck() ProcessExists("specified process") If @error Then ShellExecute("specified program", "", "Program location") Sleep(10000) pingtest() Else pingtest() EndIf EndFunc Any help would be greatly appreciated. Edited August 29, 2010 by NickT Link to comment Share on other sites More sharing options...
BrewManNH Posted August 29, 2010 Share Posted August 29, 2010 Your problem is that all of your functions are either calling themself or each other, and those functions call back to the ones that started them. You need to seperate your error checking from your functions, and NEVER call a function from within itself. Use Returns instead of calling back to Startup. You need to have an actual script/program calling functions that do things, and then return results from doing those things. Right now, all you're doing is looping back and forth between your functions and running out of stack space. If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator Link to comment Share on other sites More sharing options...
NickT Posted August 29, 2010 Author Share Posted August 29, 2010 Your problem is that all of your functions are either calling themself or each other, and those functions call back to the ones that started them. You need to seperate your error checking from your functions, and NEVER call a function from within itself. Use Returns instead of calling back to Startup. You need to have an actual script/program calling functions that do things, and then return results from doing those things. Right now, all you're doing is looping back and forth between your functions and running out of stack space.So if I understand correctly, I need to write another script that "includes" this script and make this script my function script? Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted August 29, 2010 Moderators Share Posted August 29, 2010 NickT,Not quite. You need to have a small central core of your script to which you return every now and again so that the system "unwinds" from function calls.What you are essentially doing in your current script is this:; This code will fail - it is an example of recursion limits being exceeded Global $iIndex = 1 _Print_Me() Func _Print_Me() ConsoleWrite($iIndex & @CRLF) $iIndex += 1 _Print_Me() ; call function again from within itself EndFuncYou see that it fails because you are continually calling the function from within itself. Recursion is something most coders avoid like the plague - or use very carefully if they have to use it.What you need to do is something like this:Global $iIndex = 1 While 1 _Print_Me() ; call function from within the idle loop $iIndex += 1 If $iIndex = 5000 Then Exit WEnd Func _Print_Me() ConsoleWrite($iIndex & @CRLF) ; The function now ends and returns to the idle loop EndFuncI hope you can see the difference - in the second version your function ends each time and you return to the While...WEnd loop before calling the function again. You could set the $iIndex value to anything you wanted (within AutoIt's numerical limits, of course) and you would not run into problems.You need a similar "idle" loop in your script to which you return on occasion to let the system "unwind". You can, of course, call several functions (even several times) before returning, but avoid calling any of them from within themselves.Does that make it clearer? If not, please ask again. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
NickT Posted August 30, 2010 Author Share Posted August 30, 2010 (edited) NickT, Not quite. You need to have a small central core of your script to which you return every now and again so that the system "unwinds" from function calls. What you are essentially doing in your current script is this: ; This code will fail - it is an example of recursion limits being exceeded Global $iIndex = 1 _Print_Me() Func _Print_Me() ConsoleWrite($iIndex & @CRLF) $iIndex += 1 _Print_Me() ; call function again from within itself EndFunc You see that it fails because you are continually calling the function from within itself. Recursion is something most coders avoid like the plague - or use very carefully if they have to use it. What you need to do is something like this: Global $iIndex = 1 While 1 _Print_Me() ; call function from within the idle loop $iIndex += 1 If $iIndex = 5000 Then Exit WEnd Func _Print_Me() ConsoleWrite($iIndex & @CRLF) ; The function now ends and returns to the idle loop EndFunc I hope you can see the difference - in the second version your function ends each time and you return to the While...WEnd loop before calling the function again. You could set the $iIndex value to anything you wanted (within AutoIt's numerical limits, of course) and you would not run into problems. You need a similar "idle" loop in your script to which you return on occasion to let the system "unwind". You can, of course, call several functions (even several times) before returning, but avoid calling any of them from within themselves. Does that make it clearer? If not, please ask again. M23 I think I know what to do now. Thanks Melba. I do have a couple of questions though. From what I understand, the script returns to the beginning on its own, correct? And the While loop goes through the entire process even after going to the _Print_Me() Function? Edited August 30, 2010 by NickT Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted August 30, 2010 Moderators Share Posted August 30, 2010 NickT, First, when you reply please use the "Add Reply" button at the top and bottom of the page rather then the "Reply" button in the post itself. That way you do not get the contents of the previous post quoted in your reply and the whole thread becomes easier to read. the script returns to the beginning on its own, correct?When a function ends it returns to the calling code and runs the next line. Technically there is a Return function, but unless you want to return a specific value, most coders ignore it. And the While loop goes through the entire process even after going to the _Print_Me() Function?The While loop continues with each line until it finds a WEnd at which point it restarts with the first line after the While - assuming the While condition is not met, of course. As you are obviously new to all of this (which is not a problem as we all started there!) might I suggest the excellent tutorials that you will find here and here - you will find other tutorials in the Wiki (the link is at the top of the page). You need to get a good grasp of functions and loops if you want to code anything more than the simplest of scripts. All clear now? M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
ShawnW Posted August 30, 2010 Share Posted August 30, 2010 (edited) Basically you still need a way to exit the program but I played around with your original code and kept it as intact as possible only changing the program flow to avoid stack buildup. It will loop forever and run startup(). startup() will do some things then loop forever doing 3 stages of pingtest(), time(), and runcheck(). Since time() and runcheck() didn't seem to have any conditional changes to the flow I just made them 1 time calls after pingtest(). pingtest() will return true or falls on success. I'm not sure why you have all the long sleeps in there but I left them. It will retry 7 times before causing the original startup() to return false at which point your function stack is clear and startup() gets called again because it is in a loop itself. Not sure if this is how you wanted it but I tried to make as few changes as possible. I would suggest not looping forever I just did that since your original code had no end as well. expandcollapse popup#NoTrayIcon Global $count = 0 While True startup() WEnd Func startup() $count = $count + 1 DriveMapDel("z:") Sleep(2000) If $count = 7 Then Shutdown(22) ShellExecuteWait("startup.bat", "", "c:\windows\system", "", @SW_HIDE) DriveStatus("z:") If @error Then startup() $read = FileRead("c:\log\log.txt") FileWrite("z:\log.txt", $read & @CRLF) FileDelete("c:\log\log.txt") While True $count = 0 While Not pingtest() If $count = 7 Then ShellExecuteWait("nopinglog.bat", "", "c:\windows\system", "", @SW_HIDE) ProcessClose("specified process") ProcessClose("specified process") ProcessClose("specified process") Sleep(5000) Return False EndIf WEnd time() runcheck() WEnd EndFunc ;==>startup Func pingtest() Ping("10.0.0.1", 15000) If @error Then $count = $count + 1 Sleep(5000) Return False Else $count = 0 Sleep(55000) Return True EndIf EndFunc ;==>pingtest Func time() $time = @HOUR & ":" & @MIN & ":" & @SEC If $time >= "20:00:00" And $time <= "20:01:00" Then ShellExecuteWait("pinglog.bat", "", "c:\windows\system", "", @SW_HIDE) Sleep(60000) EndIf EndFunc ;==>time Func runcheck() ProcessExists("specified process") If @error Then ShellExecute("specified program", "", "Program location") Sleep(10000) EndIf EndFunc ;==>runcheck Edited August 30, 2010 by ShawnW Link to comment Share on other sites More sharing options...
NickT Posted September 1, 2010 Author Share Posted September 1, 2010 ShawnW and M23, thank you for your help. Because of your explanations I believe I was able to figure out what I wanted to do. Here is an updated post of the script. If you have anymore suggestions, please don't hesitate. Again, thank you. #NoTrayIcon Global $count=0 While True start() drive() WEnd Func start() $count=$count+1 If $count=7 Then Shutdown(22) ProcessClose("") ProcessClose("") ProcessClose("") DriveMapDel("z:") ShellExecuteWait("") EndFunc Func drive() DriveStatus("z:") If Not @error Then $read=FileRead("c:\log\log.txt") FileWrite("z:\log.txt", $read & @CRLF) FileDelete("c:\log\log.txt") $count=0 Else Return False EndIf While 1 $d=DriveMapGet("z:") If Not $d Then Return False $count=0 While Not s_ping() If $count=7 Then ShellExecuteWait("") ProcessClose("") ProcessClose("") ProcessClose("") $count=0 Return False EndIf WEnd WEnd EndFunc Func s_ping() Ping("10.0.0.1", 15000) If @error Then $count=$count+1 Else $count=0 time() p_run() Return False EndIf EndFunc Func time() $time=@HOUR & ":" & @MIN & ":" & @SEC If $time >= "20:00:00" And $time <= "20:01:00" Then ShellExecuteWait("") EndIf EndFunc Func p_run() $p=ProcessExists("") If Not $p Then ShellExecute("") EndFunc Link to comment Share on other sites More sharing options...
bo8ster Posted September 1, 2010 Share Posted September 1, 2010 mate, please use code tags, it makes it MUCH more readable. Also look at Tidy that comes with Scite. expandcollapse popup#NoTrayIcon Global $count = 0 While True start() drive() WEnd Func start() $count = $count + 1 If $count = 7 Then Shutdown(22) ProcessClose("") ProcessClose("") ProcessClose("") DriveMapDel("z:") ShellExecuteWait("") EndFunc ;==>start Func drive() DriveStatus("z:") If Not @error Then $read = FileRead("c:\log\log.txt") FileWrite("z:\log.txt", $read & @CRLF) FileDelete("c:\log\log.txt") $count = 0 Else Return False EndIf While 1 $d = DriveMapGet("z:") If Not $d Then Return False $count = 0 While Not s_ping() If $count = 7 Then ShellExecuteWait("") ProcessClose("") ProcessClose("") ProcessClose("") $count = 0 Return False EndIf WEnd WEnd EndFunc ;==>drive Func s_ping() Ping("10.0.0.1", 15000) If @error Then $count = $count + 1 Else $count = 0 time() p_run() Return False EndIf EndFunc ;==>s_ping Func time() $time = @HOUR & ":" & @MIN & ":" & @SEC If $time >= "20:00:00" And $time <= "20:01:00" Then ShellExecuteWait("") EndIf EndFunc ;==>time Func p_run() $p = ProcessExists("") If Not $p Then ShellExecute("") EndFunc ;==>p_run Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)[topic="84960"]Brett F's Learning To Script with AutoIt V3[/topic][topic="21048"]Valuater's AutoIt 1-2-3, Class... is now in Session[/topic]Contribution: [topic="87994"]Get SVN Rev Number[/topic], [topic="93527"]Control Handle under mouse[/topic], [topic="91966"]A Presentation using AutoIt[/topic], [topic="112756"]Log ConsoleWrite output in Scite[/topic] 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