texan Posted December 3, 2007 Share Posted December 3, 2007 (edited) Since AutoIt does not have a Goto statement (It is "Evil" according to FAQ), then how would a good programmer code the following. I have a function that opens files and create objects during normal execution of the function. There are various locations in the function in which I may encounter an error that prevents me from successfully completing the function. When I encounter these errors I normally would "goto" some cleanup code at the end of the function. The cleanup code would make sure I closed all files and killed any objects. How do I properly do this without Goto? I don't want to include 10 lines of cleanup code in every location I check for errors. I am admittedly a little bit of an 'old school' programmer at times and I don't think the Goto is "evil" but I have worked with some older school programmers that can miss use it. Edited December 3, 2007 by texan Link to comment Share on other sites More sharing options...
weaponx Posted December 3, 2007 Share Posted December 3, 2007 Just put whatever is in your goto code inside a function. ;Doing stuff ;Doing stuff ;Oh crap thats not good cleanup() Func cleanup() ;remove objects EndFunc Link to comment Share on other sites More sharing options...
Valuater Posted December 3, 2007 Share Posted December 3, 2007 Just put whatever is in your goto code inside a function. ;Doing stuff ;Doing stuff ;Oh crap thats not good cleanup() Func cleanup() ;remove objects EndFunc Good answer... here is a small example expandcollapse popup; COM Error Handler example ; ------------------------- $oIE=ObjCreate("InternetExplorer.Application.1") ; Create Internet Explorer application $oMyError = ObjEvent("AutoIt.Error","MyErrFunc") ; Initialize a COM error handler $oIE.UnknownMethod ; Deliberately call an undefined method If @error then Msgbox (0,"AutoItCOM test","Test passed: We got an error number: " & @error) Clean_Up($oIE) Else Msgbox (0,"AutoItCOM test","Test failed!") Endif Exit ; This is my custom defined error handler Func MyErrFunc() Msgbox(0,"AutoItCOM Test","We intercepted a COM Error !" & @CRLF & @CRLF & _ "err.description is: " & @TAB & $oMyError.description & @CRLF & _ "err.windescription:" & @TAB & $oMyError.windescription & @CRLF & _ "err.number is: " & @TAB & hex($oMyError.number,8) & @CRLF & _ "err.lastdllerror is: " & @TAB & $oMyError.lastdllerror & @CRLF & _ "err.scriptline is: " & @TAB & $oMyError.scriptline & @CRLF & _ "err.source is: " & @TAB & $oMyError.source & @CRLF & _ "err.helpfile is: " & @TAB & $oMyError.helpfile & @CRLF & _ "err.helpcontext is: " & @TAB & $oMyError.helpcontext _ ) Local $err = $oMyError.number If $err = 0 Then $err = -1 SetError($err) ; to check for after this function returns Endfunc Func Clean_Up(ByRef $Input) $Input = "" Msgbox (0,"Clean Up","The Object has been Cleaned " & @CRLF & IsObj($Input), 3) ; do something else ?? EndFunc there are MANY answers to your question 8) Link to comment Share on other sites More sharing options...
PsaltyDS Posted December 3, 2007 Share Posted December 3, 2007 Since AutoIt does not have a Goto statement (It is "Evil" according to FAQ), then how would a good programmer code the following. I have a function that opens files and create objects during normal execution of the function. There are various locations in the function in which I may encounter an error that prevents me from successfully completing the function. When I encounter these errors I normally would "goto" some cleanup code at the end of the function. The cleanup code would make sure I closed all files and killed any objects. How do I properly do this without Goto? I don't want to include 10 lines of cleanup code in every location I check for errors. I am admittedly a little bit of an 'old school' programmer at times and I don't think the Goto is "evil" but I have worked with some older school programmers that can miss use it. Your error handler would be a function. Then, when the error was detected, you would call the handler - then return: _DoMyStuff() Func _DoMyStuff() Local $sSource = "C:\Temp\Test1.txt" Local $sDestination = "C:\Temp\Test2.txt" If FileExists($sDestination) Then If Not FileCopy($sDestination, $sDestination & ".BAK", 1) Then _FileCopyError($sDestination, $sDestination & ".BAK") Return SetError(1, 1, 0) EndIf EndIf If Not FileCopy($sSource, $sDestination) Then _FileCopyError($sSource, $sDestination) Return SetError(1, 2, 0) EndIf EndFunc ;==>_DoMyStuff Func _FileCopyError($sSrc, $sDest) FileDelete($sDest) MsgBox(16, "Error", "An error occured while copying:" & @CRLF & _ "From: " & $sSrc & @CRLF & _ "To: " & $sDest & @CRLF & _ "Destination file deleted.") Return EndFunc ;==>_FileCopyError And keep your list current. Evil: Goto, Assign, and Eval Like loud song in the Mead Hall, too much whining about GOTO will bring The Grendel Valik out of his cave. So beware your careless ways... Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
texan Posted December 3, 2007 Author Share Posted December 3, 2007 Yeah, I figured the answer was to use a function. I guess in my old school way of thinking, using a function requires more code so I don't like it.Instead of this:If ErrorCondition Then Goto CleanupCodeEndIfNow I must use this:If ErrorCondition Then Call CleanupCode() Exit FunctionEndIfthere are MANY answers to your questionWhat other answers are there? Link to comment Share on other sites More sharing options...
weaponx Posted December 3, 2007 Share Posted December 3, 2007 Yeah, I figured the answer was to use a function. I guess in my old school way of thinking, using a function requires more code so I don't like it.Instead of this:If ErrorCondition Then Goto CleanupCodeEndIfNow I must use this:If ErrorCondition Then Call CleanupCode() Exit FunctionEndIfWhat other answers are there?Not even that much code is needed.If NOT FileExists ( "XYZ" ) Then Cleanup()Func Cleanup()EndFuncThere is no need to "Call" or "Exit" Function Link to comment Share on other sites More sharing options...
PsaltyDS Posted December 3, 2007 Share Posted December 3, 2007 Not even that much code is needed.If NOT FileExists ( "XYZ" ) Then Cleanup()Func Cleanup()EndFuncThere is no need to "Call" or "Exit" FunctionDoesn't exit the function that had the error, which I thought he wanted. Like if the error happens on the third of five steps in a function, do cleanup and then exit the function.I could be wrong. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
weaponx Posted December 3, 2007 Share Posted December 3, 2007 (edited) I was under the impression that since the OP was unfamiliar with functions we wouldn't need to exit a function when the Cleanup() is complete. Edited December 3, 2007 by weaponx Link to comment Share on other sites More sharing options...
Valuater Posted December 3, 2007 Share Posted December 3, 2007 Doesn't exit the function that had the error, which I thought he wanted. Like if the error happens on the third of five steps in a function, do cleanup and then exit the function.I could be wrong. I would think the OP needed a registered error handler due to working with objects... Call() is evil too.... 8) Link to comment Share on other sites More sharing options...
PsaltyDS Posted December 3, 2007 Share Posted December 3, 2007 ...and I made a Valik funny, and nobody noticed. Hrumph! Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
weaponx Posted December 3, 2007 Share Posted December 3, 2007 ...and I made a Valik funny, and nobody noticed. Hrumph! I noticed but it wasn't so much funny as it was true. Link to comment Share on other sites More sharing options...
therks Posted December 3, 2007 Share Posted December 3, 2007 Instead of this: If ErrorCondition Then Goto CleanupCode EndIf Now I must use this: If ErrorCondition Then Call CleanupCode() Exit Function EndIf Could even do it like this: If ErrorCondition Then Exit CleanupCode() EndIf Func CleanupCode() ; Do your cleanup stuff here EndFunc So it's really only one more line (EndFunc). Alternatively, you can use multiple functions with Return statements to simulate Goto. My AutoIt Stuff | My Github Link to comment Share on other sites More sharing options...
Valuater Posted December 4, 2007 Share Posted December 4, 2007 (edited) What other answers are there?Well, I think you have been shown a few... hope one is right for your use! ...and I made a Valik funny, and nobody noticed. Hrumph! I noticed but, I figured if you want to go out on a limb talking about Valik... You're on your own!... 8) Edited December 4, 2007 by Valuater Link to comment Share on other sites More sharing options...
DirtDBaK Posted December 4, 2007 Share Posted December 4, 2007 never seen his wrath but i've heard stories from the nice ban list... [center][/center] Link to comment Share on other sites More sharing options...
PsaltyDS Posted December 4, 2007 Share Posted December 4, 2007 Could even do it like this: If ErrorCondition Then Exit CleanupCode() EndIf Func CleanupCode() ; Do your cleanup stuff here EndFunc So it's really only one more line (EndFunc). Alternatively, you can use multiple functions with Return statements to simulate Goto. Oh, I like that! Here's my version: _DoMyStuff() Func _DoMyStuff() Local $sSource = "C:\Temp\Test1.txt" Local $sDestination = "C:\Temp\Test2.txt" Local $sBak = $sDestination & ".BAK" If FileExists($sDestination) Then If Not FileCopy($sDestination, $sBak, 1) Then Return SetError(1, _FileCopyError($sDestination, $sBak), 0) EndIf If Not FileCopy($sSource, $sDestination) Then Return SetError(1, _FileCopyError($sSource, $sDestination), 0) EndFunc ;==>_DoMyStuff Func _FileCopyError($sSrc, $sDest) FileDelete($sDest) MsgBox(16, "Error", "An error occured while copying:" & @CRLF & _ "From: " & $sSrc & @CRLF & _ "To: " & $sDest & @CRLF & _ "Destination file deleted.") Return EndFunc ;==>_FileCopyError Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Jango Posted December 4, 2007 Share Posted December 4, 2007 (edited) Hi, I think a good way can be also: Opt("OnExitFunc", "CleanUp") Global ErrorCondition = 0 ; Do whatever that set ErrorCondition if an error is encountered If ErrorCondition Then Exit Exit Func Cleanup() If ErrorCondition Then ; Do your cleanup stuff here EndIf EndFunc Edited December 4, 2007 by Jango Link to comment Share on other sites More sharing options...
texan Posted December 4, 2007 Author Share Posted December 4, 2007 Hi, I think a good way can be also: Opt("OnExitFunc", "CleanUp") Global ErrorCondition = 0 ; Do whatever that set ErrorCondition if an error is encountered If ErrorCondition Then Exit Exit Func Cleanup() If ErrorCondition Then ; Do your cleanup stuff here EndIf EndFunc Thanks for all of the good ideas. I think this OnExitFunc method is my favorite and I did not know this feature existed or I would have used it to begin with. Historically, when I code any function, I always had a "cleanup" section at the bottom of the function. If there were no errors in the function you would end up "falling through" the cleanup section. If there were errors, I would "goto" the cleanup section. For some functions the cleanup section would be empty but I always left it in just because it was my standard method of coding functions. I really like this OnExitFunc feature because it accomplishs the exact same thing I was always doing with "goto cleanup". Link to comment Share on other sites More sharing options...
Valik Posted December 4, 2007 Share Posted December 4, 2007 (edited) I'm sure you'll abuse this: Func MyFunc() Local $nError, $nExtended, $vResult ; Pseudo Loop Do ... Stuff If @error Then $nError = 1 $vResult = False ExitLoop EndIf ... Stuff If @error Then $nError = 2 $vResult = False ExitLoop EndIf ; More stuff, no more errors $vResult = True Until True ; Cleanup Return SetError($nError, $nExtended, $vResult) EndFunc It implements a Do...Until loop which will only execute once. Since the bulk of the code is contained inside a loop, when you encounter an error and need to go to the cleanup section, set the variables for the returned values and ExitLoop. I use this when I need to clean up handles or something and there are multiple points of failure. I do not recommend writing every single function this way as the number of functions which require cleanup is few. Your "I always had a cleanup label" you mentioned was just pure laziness. Edited December 4, 2007 by Valik Link to comment Share on other sites More sharing options...
rover Posted December 4, 2007 Share Posted December 4, 2007 just some food for thought as an addendum this post has a code example from ChrisL GUIRegisterMsg windows message handler for system shutdown message WM_QUERYENDSESSION if program running during system initiated shutdown, apparently at times OnAutoItExit doesn't run I use both _ShutdownInitiated and OnAutoItExit OnAutoItExit() during Shutdown isn't processed I think $WM_QUERYENDSESSION declaration can be left out if using 3.2.10.0 Global $WM_QUERYENDSESSION = 0x0011 GUICreate("ShutDownNotificationGui") GUIRegisterMsg($WM_QUERYENDSESSION, "_ShutdownInitiated") GUISetSTate(@SW_HIDE) While 1 sleep(10) WEnd Func _ShutdownInitiated($hWndGUI, $MsgID, $WParam, $LParam) ; cleanup ProcessClose("the other process that is relaunching this app.exe");or the net stop thing you posted above RunWait("net stop Login-restarter","",@SW_HIDE) Return True ; reports back to system EndFunc I see fascists... Link to comment Share on other sites More sharing options...
Anteaus Posted December 4, 2007 Share Posted December 4, 2007 (edited) How do I properly do this without Goto? I don't want to include 10 lines of cleanup code in every location I check for errors. My way of coding this is to put the procedure into a function, and use a Return($value) statement to break-out of the function if anything goes wrong. You can of course have as many Return() statements as you like. Back in the main prog, we examine the returned value to see if the process succeeded or not, and if not, where it failed. We then run the cleanup routine based on this info. Only possible issue is that the cleanup routine will not have access to any private values which the function held. Whether that matters depends on the situation. e.g. func DoWhateverJob() ; Perform stage 1 if <error occurred> then Return 1 ; Perform stage 2 if <error occurred> then Return 2 ; Perform stage 3 if <error occurred> then Return 3 Return 0 endfunc ; main prog: $returncode=DoWhateverJob() if $returncode > 0 then msgbox(0, "Error" , "Procedure failed at stage " & $returncode) ; do cleanup here endif HST, I reckon we should campaign for the Fortran multiple-calculated-value GOTO statement. Edited December 4, 2007 by Anteaus 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