MaximusNeo701 Posted April 8, 2013 Share Posted April 8, 2013 Been using autoit here for for about 6 months. I am a software dev, and it is very useful to help automate tasks for work so I can spend my time accomplishing other goals but I believe I have come across a pretty serious bug in the way Autoit executes scripts. This in my experience has applied to while and for loops but I believe it extends to any loops inside of loops. The easiest example of this bug I can explain is on for loops For $i = 1 To 8 Local $oInputs = _IETagNameGetCollection($oIE, "input") For $oInput In $oInputs if $oInput.value = "SOMEVALUE" Then $ButtonObject = $oInput EndIf Next MyFunction( $oInput) Next this is actual code I have been working on but I changed a few names of things to make it very generic. So we would expect the initial For loop to execute 8 times now, and inside each of those 8 runs to find the object on the webpage I am looking for. But the issue is that my loop only runs 4 times? So I jumped it up 1 to 16 on my bounds on the outermost For loop and it runs 8 times. Great so it works right? Well it seems to me that at some point when the token "Next" is encountered that it must also for some reason be increasing my outermost For loop counter when it should not. But I know for a fact that isn't really the case since it would have to step through the innermost loop about 30 times (lots of elements on the IE page,) so it only seems to be increasing the outermost For loop counter upon exiting the the innermost loop. Sounds like something with the looping stack isn't working correctly. Here is the example of the while loops that didn't work correctly, now I will say this isn't copied and pasted from my code as I undid the work since it didn't work and I had a theory loops had an issue but wasn't able to observe it correctly until now. The code will be very very psuedo code to make reading easier setupProgramData() while(1) sleepUntilProgramStartTime($startTime) <-- this was initially a while loop also but would stay inside the loop until I made it a method dostuff() $rs = getSomeSQLRecords() While $rs.EOF = False doStuffWithSQLData($rs) WEnd cleanup() WEnd Now what happened here if I remember correctly, whenever the WEnd was encountered leaving the innermost While Loop the software would break. I cannot recall exactly what happened, but with msgbox outputs and spitting out values I could see then things went south. It ran perfectly before I tried to implement this idea of never stop running and just begin again when it was the proper time by using the outermost while loop. I did test just getting a message box at the right time and it also did work; so I know by itself the outermost loop did also work. Just when nesting loops Autoit becomes not very happy. This issue doesn't seem to arise when I have a loop inside of a function/method and call said function/method inside of that loop. It just seems to be an issue when loops are nested within the same function/method. If anyone has any input or feedback for me I would greatly appreciate it, or to at least know if this is a known issue. Link to comment Share on other sites More sharing options...
czardas Posted April 8, 2013 Share Posted April 8, 2013 (edited) This issue doesn't seem to arise when I have a loop inside of a function/method and call said function/method inside of that loop.Here may be a clue. I suspect that you may be altering the iteratioon count $i in the function called within the loop. If you put your nested For loops inside another function, chances are it will be fixed. If $i is a global variable, it can potentially be altered by any function called on within your loop. Edited April 8, 2013 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
MaximusNeo701 Posted April 9, 2013 Author Share Posted April 9, 2013 I have checked on this, $i is a local variable. Also in the example above $i is used on the outermost loop and $oInput In $oInputs on the innermost loop; so that should not be an issue, that section was copy and pasted and I just changed a variable name to SOMEVALUE. A quick ctrl+f on the software to be sure there were no more uses of the variable $i, but I do appreciate the feedback.Also that still leaves the while loop issue unresolved; as I am getting ready for a major updated with new functionality I would like to be able to go into it without fearing this problem again. Link to comment Share on other sites More sharing options...
czardas Posted April 9, 2013 Share Posted April 9, 2013 (edited) All the variables in the code you posted are global variables. They are not assigned locally within a function, but rather local to the global scope (outside of any function). If this is not the case in your original script, then there is most likely a bug you created somewhere else in your code. Local $i Local $iLoopCount = 0 For $i = 0 To 9 $iLoopCount += 1 _Interference() ; This introduces a bug. Next MsgBox(0, "Loop Count", $iLoopCount) Func _Interference() $i = 10 EndFunc If you really think you have found a bug in AutoIt, post code that demonstrates this. The code you posted does not demonstrate what you claim to be a bug. Edited April 9, 2013 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
jdelaney Posted April 9, 2013 Share Posted April 9, 2013 (edited) _Interference() ; This introduces a bug. By default when variables are declared using Dim or assigned in a function they have Local scope unless there is a global variable of the same name (in which case the global variable is reused). This can be altered by using the Local and Global keywords to declare variables and force the scope you want. Local $i Local $iLoopCount = 0 For $i = 0 To 9 $iLoopCount += 1 _Interference() Next MsgBox(0, "Loop Count", $iLoopCount) Func _Interference() Local $i = 10 EndFunc I'm guessing 'global' is relative...the local for the scrip is a higher level than the variable set in the function (which is why it overrides the 'global' (actually local $i, line 1)), unless specifically defined as local (in the function), like above...i've always found it much easier to append a small string after variables, to ensure I don't over-ride my variables...like $i_FuncName Edited April 9, 2013 by jdelaney IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window. Link to comment Share on other sites More sharing options...
czardas Posted April 9, 2013 Share Posted April 9, 2013 (edited) I understand how that works. I'm not so sure that the OP knows this though. Dim is meant to be depreciated. There must be some reason why the OP's code is not working as expected. We would have to see more of the code to figure that out. Edited April 9, 2013 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
jdelaney Posted April 9, 2013 Share Posted April 9, 2013 (edited) Yep, it all depends on what he is doing in MyFunction( $oInput) Which, it shouldn't be 100% doing what he wants either...the sudo code should look like this: For $i = 1 To 8 Local $oInputs = _IETagNameGetCollection($oIE, "input") For $oInput In $oInputs If $oInput.value = "SOMEVALUE" Then $ButtonObject = $oInput ExitLoop EndIf Next MyFunction($ButtonObject) Next or this For $i = 1 To 8 Local $oInputs = _IETagNameGetCollection($oIE, "input") For $oInput In $oInputs If $oInput.value = "SOMEVALUE" Then MyFunction($oInput) ExitLoop EndIf Next Next Edited April 9, 2013 by jdelaney czardas 1 IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window. Link to comment Share on other sites More sharing options...
MaximusNeo701 Posted April 9, 2013 Author Share Posted April 9, 2013 (edited) Thanks for the feedback, I do not use dim as I am aware of the issue of local vs global variables and reusing a global could cause an issue. MyFunction was just stubbed in; and still an empty method when I posted it. The entire method I am having this issue with is now posted. if Not($imagedir = "none") Then local $FileList = _FileListToArray($imagedir) if @error = 0 Then local $FileList = _ArrayShuffle($FileList,1,$FileList[0]) For $i = 1 To 16 Local $oInputs = _IETagNameGetCollection($oIE, "input") For $oInput In $oInputs if $oInput.value = "add image" Then local $uploadButtonObject = $oInput EndIf Next _IEAction ($uploadButtonObject, "click") ControlClick("[CLASS:IEFrame]", "", "[CLASS:Internet Explorer_Server; INSTANCE:1]", "Left", 1, 350, 270) Sleep($SLEEPTIMER) ControlSetText("Choose File to Upload","", "[CLASS:Edit; INSTANCE:1]", $imagedir & $FileList[$i]) sleep(1000) ControlClick("Choose File to Upload", "","[CLASS:Button; INSTANCE:1]") sleep($SLEEPTIMER + 10000) Next EndIf EndIf $i used in the FileList[] is so that I can access the filename stored in that array, and I would like it to loop 8 times. This is the entire method after some refactoring. I ran a test by removing the inner most loop and the issue went away. I appreciate the feedback, the reason MyFunction()'s code was not posted was because it was just stubbed, I don't make a habit of asking for help without providing all the pertinent info though. I also tested just calling this Method alone and I am still seeing the same issue with no other code being executed. Also I meant no offense to anyone who helps work on Autoit, I most likely should have put a ? on the end as I haven't been able to solve this solution. Edited April 9, 2013 by MaximusNeo701 Link to comment Share on other sites More sharing options...
kylomas Posted April 9, 2013 Share Posted April 9, 2013 MaximusNeo701, I don't see anything in your code that shows the number of iterations for any for...to loops. How do you know how many time they are iterating? kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill Link to comment Share on other sites More sharing options...
MaximusNeo701 Posted April 9, 2013 Author Share Posted April 9, 2013 For $i = 1 To 166th line the first loop, it may not have shown up well I was editing to fix the indentations which did not copy over Link to comment Share on other sites More sharing options...
kylomas Posted April 9, 2013 Share Posted April 9, 2013 (edited) No, that means nothing...$i can be altered. I suggest a consolewrite in every supect loop to verify this. kylomas edit: additional info Run this for $i = 1 to 5 ConsoleWrite($i & @LF) for $j = 1 to 5 ConsoleWrite(@tab & $j & @LF) Next next Your problem lies elsewhere. Edited April 9, 2013 by kylomas Forum Rules Procedure for posting code "I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals." - Sir Winston Churchill Link to comment Share on other sites More sharing options...
MaximusNeo701 Posted April 9, 2013 Author Share Posted April 9, 2013 No, that means nothing...$i can be altered. I suggest a consolewrite in every supect loop to verify this. kylomas edit: additional info Run this for $i = 1 to 5 ConsoleWrite($i & @LF) for $j = 1 to 5 ConsoleWrite(@tab & $j & @LF) Next next Your problem lies elsewhere. Was actually already contemplating doing this since I started the thread but haven't had time. Though from that code I do not see $i being edited so still stumped. 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