qwert Posted August 5, 2008 Share Posted August 5, 2008 I think this might be a tough one, so please understand that I'm posting this more in the spirit of a "heads up" for anyone encountering similar problems and less in the hope of finding a solution. I've been troubleshooting "Line -1 Error: Array ... " occurrences for about six months now, trying to get a handle on what the problem might be -- and hoping to catch something specific. Here's the situation:I have a set of scripts that are individually called by an external application to make adjustments to that external application's window settings, among other things. The scripts are compiled (and obfuscated) and then installed along with the main application. Individual calls to a script pass up to 3 parameters that specify exactly the window adjustment to be performed.Note that I can't simply run the script.au3 files (to possibly get a detailed error message) because the external app is calling them by name ("script.exe"), so they must be the compiled versions. It's also worth mentioning that when I test the same scripts by initiating them with command line requests, I never receive any array errors.Here are the "clues" I have gathered:1) The Error:Array seems to be somehow extraneous to a script's proper execution. In other words, script actually works when called (it performs its intended task). 2) The following steps are at the beginning of each script, but the message has never displayed in my testing: If (Not IsArray($CmdLine)) Or ($CmdLine[0] = 0) Then MsgBox(32, "Invalid Request", Hex($hWnd))3) Obfuscated, a script is prone to the error. Non-obfuscated, it isn't (the Error never occurs).4) The error is related to execution speed. It's prone to the errors on slower PCs, but almost never on fast ones. (Fails on Celeron 1.5 Ghz ... succeeds on Pentium4 3.0 Ghz)If the error reporting popup could just give some attribute of the script ... the PID, the array contents, the Dll being called ... just about anything would help. It took quite a while to even isolate which of my two scripts were actually involved in the error. It would certainly help to know more about how AutoIt3 detects an array problem -- and when it builds the error message. Is it solely an Au3 check performed as a script is interpreted? Or is it in response to an error return from a Dll call to the O/S?Any information will be appreciated. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted August 5, 2008 Moderators Share Posted August 5, 2008 I don't remember ever getting this error on any of my pc's. Do you have a replication script that does the same thing? You also may consider using a debug option within the script, have it write to the console and have another executable read the stderrread/stdoutread. 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. Link to comment Share on other sites More sharing options...
qwert Posted August 5, 2008 Author Share Posted August 5, 2008 Thanks for the response. Do you have a replication script that does the same thing?Here's the first portion of one of the scripts: #NoTrayIcon #include <Misc.au3> _Singleton("Taskbar Utility") Opt("WinTitleMatchMode",4) $hWnd = WinGetHandle("Classname=Shell_TrayWnd") $button = WinGetHandle("Start") Sleep(20) If (Not IsArray($CmdLine)) Or ($CmdLine[0] = 0) Then MsgBox(32, "Invalid Request", Hex($hWnd)) ; this message is NEVER displayed Exit EndIf Exit ; Exit is included to isolate problem ; Normally, changes to task bar start here ; using parameter passed by calling application I'm afraid I don't follow what you're suggesting. Could you explain how steps could be added to the above sequence to trap some details? Or what should be written to the console? Because the script works, I wouldn't expect the parameters themselves to reveal anything. It seems more of a task-level housekeeping issue. But I'll try anything. Link to comment Share on other sites More sharing options...
Zedna Posted August 5, 2008 Share Posted August 5, 2008 For testing if it's related to CPU speed you may use small FREE utility Sleeper http://www.slunecnice.cz/product/Sleeper/http://www.slunecnice.cz/product/Sleeper/download.htmlIt slow down CPU, so rendering of picture control is nice visible.Note Sleeper trackbar must be at less than 10% (may be also 0%).Look here: http://www.autoitscript.com/forum/index.ph...st&p=101138 Resources UDF Â ResourcesEx UDF Â AutoIt Forum Search Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted August 5, 2008 Moderators Share Posted August 5, 2008 1st part: Open your script in SciTe. Tools Add trace lines Compile 2nd part. Make a helper exe or something that is the middle man from your main script to your scripts that are having issues. In the helper exe, you'll pass from the main exe the executable name to launch, and the command line parameters to pass with it. After launching with Run (making sure that run has a variable)ie.. $iPID = Run('"' & $cmdline[1] & '" "' & $s_params & '"', "", @SW_HIDE, 6) While Not @error $s_consoleread = stdoutread($iPID) WEnd FileWrite($s_log_file, $s_consoleread) That's just a rough concept without writing it for you. You should be able to track what is going on step by step that way. 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. Link to comment Share on other sites More sharing options...
qwert Posted August 6, 2008 Author Share Posted August 6, 2008 You should be able to track what is going on step by step that way.Although it will take some time, I'm certainly willing to give this a try, but one thing concerns me: How will the helper script be able to receive the cmdLine array any better than the real script? I know it's always possible to miss something, but I've looked very closely at the logic in each script and can't see any possibility of an error IF the script receives any array at all. It tests CmdLine[0] for each possible case and exits when a valid case is found -- or puts up a message if none is found. BTW, I can't modify the main application, so I'll have to change the two problem scripts to be individual helper tasks. At minimum, I suppose this will determine if it's an array passing problem (which I suspect) or an array processing problem (which I don't). At this point, I think I'll skip implementing the tracing and just confirm the script calls. Further comments are welcome. Link to comment Share on other sites More sharing options...
qwert Posted August 6, 2008 Author Share Posted August 6, 2008 Given the suggestions that have been made, I decided to try one thing before launching into a more complicated investigation:I removed all processing from one of the scripts that fails -- making the runtime version just like what is shown in my second post above. Then I launched it from the main application and immediately launched it a second time. That resulted in a "Line -1 Error:Array..." I repeated the test 10 times and got the error on 7 of them.This tells me that the CmdLine parameter passing is being corrupted when the first copy of the script exits. Maybe the memory holding the parameters gets released back to the operating system, even though it's holding parameters for the second call at that point. (I thought the Singleton function kept two copies from running at the same time -- or maybe Singleton is the culprit?)Visualizing the possibilities here is a bit beyond my level right now, but I think I'm closer to understanding what operational conditions are causing the error. I will welcome any suggestions on how to prevent the problem entirely. I must add that, during normal operation, the script calls shouldn't occur back-to-back -- but I suppose if a script is paused by the OS for any reason, then a second call could occur on top of the first. Link to comment Share on other sites More sharing options...
martin Posted August 6, 2008 Share Posted August 6, 2008 This might not be your problem but the line If (Not IsArray($CmdLine)) Or ($CmdLine[0] = 0) Then is faulty. If $cmdLine is not an array then $CmdLIne[0] will cause an error. You need something like this if not IsArray($CmdLine) then msgbox(.. exit endif if $CmdLine[0] = 0 then msgbox(... exit endif Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted August 6, 2008 Moderators Share Posted August 6, 2008 This might not be your problem but the line If (Not IsArray($CmdLine)) Or ($CmdLine[0] = 0) Then is faulty. If $cmdLine is not an array then $CmdLIne[0] will cause an error. You need something like thisAlthough I agree that the syntax isn't written correctly. $cmdline is always an array, and if it were just an array check, and it failed, the $cmdline[0] = 0 statement would never happen. Dim $a_is_not_an_array If Not IsArray($a_is_not_an_array) Or $a_is_not_an_array[0] = 1 Then MsgBox(16, "Error", "Not an array or $a_is_not_an_array[0] = 1") EndIf 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. Link to comment Share on other sites More sharing options...
qwert Posted August 6, 2008 Author Share Posted August 6, 2008 martin, that's an excellent observation. I hadn't considered that the test itself could error out.SmOke_N, two things:1. Can I assume you meant "$cmdline isn't always an array"?2. I can't get my head around the use of "Not IsArray($a_is_not_an_array)" Can you restate it using $CmdLine as the array? Or explain how the two arrays relate?But my overriding question at this point is about the possibility of an OS-level issue:What if the parameter "stack" or whatever is being released upon exiting the first script -- but by that time it contains parameters from the second script.I mentioned previously that it seemed unlikely that one of my scripts would be called immediately again -- although for testing, I forced that case. Well, upon further analysis, it's much more likely that a window adjustment script might overlap a taskbar adjustment script -- and parameters are passed to both.Is it possible that there's a subtle conflict between scripts that has never been recognized? It would only occur in the extremely rare case that:1. Two scripts are active at the same time2. Both scripts have parameters passed to them3. One of the scripts performs an Exit while the other is being initialized.It would be comforting if someone with knowledge of the internals of runtime execution could render an opinion. Is such a conflict possible? Or is it simply an illusion and the case can be resolved by tests of the array? If so, what is a reliable test?Thanks very much for the responses. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted August 6, 2008 Moderators Share Posted August 6, 2008 (edited) martin, that's an excellent observation. I hadn't considered that the test itself could error out.SmOke_N, two things:1. Can I assume you meant "$cmdline isn't always an array"?2. I can't get my head around the use of "Not IsArray($a_is_not_an_array)" Can you restate it using $CmdLine as the array? Or explain how the two arrays relate?But my overriding question at this point is about the possibility of an OS-level issue:What if the parameter "stack" or whatever is being released upon exiting the first script -- but by that time it contains parameters from the second script.I mentioned previously that it seemed unlikely that one of my scripts would be called immediately again -- although for testing, I forced that case. Well, upon further analysis, it's much more likely that a window adjustment script might overlap a taskbar adjustment script -- and parameters are passed to both.Is it possible that there's a subtle conflict between scripts that has never been recognized? It would only occur in the extremely rare case that:1. Two scripts are active at the same time2. Both scripts have parameters passed to them3. One of the scripts performs an Exit while the other is being initialized.It would be comforting if someone with knowledge of the internals of runtime execution could render an opinion. Is such a conflict possible? Or is it simply an illusion and the case can be resolved by tests of the array? If so, what is a reliable test?Thanks very much for the responses.$cmdline is an AutoIt variable, it cannot be used for anything other than what it was designed for. It is always an array when passing command line parameters. So you can always assume it will be an array.My post demonstrates, that if you check if a variable is an array first with IsArray, if IsArray fails, then the Or conditional statement is never even checked, so that could not fail.Your questions are confusing. I don't have the 3 scripts to even start to understand or imagine what you are trying to achieve or what is exactly happening.From what I can gather from your posts, you are assuming that once you call a script, pass the command line parameters, that the script that passed the command line ends, the variables are destroyed for both scripts, that isn't true if that's the case. The variables are destroyed in memory from the script that exits only.If you don't want two of the same scripts running, then use the Singleton function at the top (before command lines) of your script (the one you don't want to run more than once, if you don't want any of the 3 to run more than once, put it at the top of all 3 with their own unique string (GUID) for recognition). Edited August 6, 2008 by SmOke_N 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. Link to comment Share on other sites More sharing options...
qwert Posted August 6, 2008 Author Share Posted August 6, 2008 Your questions are confusing. I don't have the 3 scripts to even start to understand or imagine what you are trying to achieve or what is exactly happening.True, I never exactly explained the full context -- which didn't seem relevant until now.I have a main application (not a script) that performs the following:Call ScriptA (with parameters) to adjust application's windowCall ScriptB (with parameters) to adjust contents of taskbarMy concern is that ScriptA's Exit is somehow releasing some portion of "AutoIt runtime memory" that happens, at that moment, to contain parameters being passed to ScriptB. This would also help make sense of the timing issue where I haven't seen failures on fast computers -- probably because the time window of opportunity for failure is much smaller. In other words, it should eventually fail. I just haven't seen it happen yet. Link to comment Share on other sites More sharing options...
qwert Posted August 6, 2008 Author Share Posted August 6, 2008 Unless I'm missing some aspect of this entirely, my latest test seems to point clearly to an AutoIt problem that only occurs when an external application is launching scripts with command line parameters.I've reduced my test case to only the calling program and ScriptA. The script is called each time a button is pressed on the application's main screen. I've also reduced ScriptA to simply unload the passed parameters into local variables and then exit. Here are my results:If I allow ScriptA to complete entirely, clicking the request button again simply causes ScriptA to execute again. I never get an array error.However, if I click the request button twice in succession, I often get the array error -- not every time, but at least 50%In either case, the tests for IsArray and CmdLine[0] = 0 never detect a positive. Indeed, in all my testing, I have never received either message. It leads me to conclude that neither test is necessary as long as the calling program can be trusted. This leads me to conclude further that my scripts are sometimes executing without an array present in their workspace.I would very much like to hear if anyone else can reproduce the array error. In other words, have a C++ program or equivalent with a simple button that makes a command line call to an AutoIt script and passing a single parameter. Increase the frequency of button clicks and see if an array error occurs.Thanks for any assistance. Link to comment Share on other sites More sharing options...
Spiff59 Posted August 6, 2008 Share Posted August 6, 2008 I have a commercial application (Medisoft) where I hijacked a program button that launched an external link to thier cheesy word processor (I've just named my AutoIt executable to replace their word processor application). Medisoft does pass parameters, some of which I use. I am unable to cause an error no matter how fast I click on the "launch" button. I can cease some rapid-clicking and sit back and watch the last couple calls flash by.I do use the _Singleton command to kill previous instances of my script, prior to referencing the passed parameters. That may suppress my possibility of incurring your exact error. It doesn't seem like your users would purposely be performing those tasks in rapid succession? Is it just the occasional inadvertant double-click you're trying to handle? If so, you could use _Singleton to wait until the prior process has finished, or just kill it if that's allowable, before allowing the new process to proceed?I'm far from an expert here, but I do find this interesting... 3) Obfuscated, a script is prone to the error. Non-obfuscated, it isn't (the Error never occurs).Do this statement still apply with your latest batch of tests???(I have not enabled obfuscation on any of my compiles) Link to comment Share on other sites More sharing options...
qwert Posted August 6, 2008 Author Share Posted August 6, 2008 Spiff59, an excellent observation!I failed to go all the way back and test without obfuscation. It is somehow the cuprit.Here is a very simple version of what I have been testing with:#NoTrayIcon #Region;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Run_Obfuscator=y #EndRegion;**** Directives created by AutoIt3Wrapper_GUI **** #include <Misc.au3> _Singleton("Test Utility") If Not IsArray($CmdLine) Then MsgBox(32, "Alert", "Invalid Array") Exit EndIf If $CmdLine[0] = 0 Then MsgBox(32, "Alert", "Invalid request") Exit EndIf $request = $CmdLine[1] ; capture the parameter immediately Exit ; Exit is included to isolate problem ; Normally, the script's processing starts here ; using parameters passed by calling applicationUnobfuscated, it executes without error -- no matter how fast I make requests.Obfuscated, it fails within a few rapid clicks.Can you substitute the above code for your test routine and then try it both ways? Link to comment Share on other sites More sharing options...
qwert Posted August 12, 2008 Author Share Posted August 12, 2008 Unobfuscated, it executes without error -- no matter how fast I make requests. Obfuscated, it fails within a few rapid clicks. #NoTrayIcon #Region;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Run_Obfuscator=y #EndRegion;**** Directives created by AutoIt3Wrapper_GUI **** #include <Misc.au3> _Singleton("Test Utility") If Not IsArray($CmdLine) Then MsgBox(32, "Alert", "Invalid Array") Exit EndIf If $CmdLine[0] = 0 Then MsgBox(32, "Alert", "Invalid request") Exit EndIf $request = $CmdLine[1]; capture the parameter immediately Exit; Exit is included to isolate problem ; Normally, the script's processing starts here ; using parameters passed by calling application I wanted to try one last time to reach a conclusion on what I've observed. If anyone has a few minutes, I would greatly appreciate an independent confirmation of the results. Thanks for any help. Link to comment Share on other sites More sharing options...
martin Posted August 12, 2008 Share Posted August 12, 2008 (edited) #NoTrayIcon #Region;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Run_Obfuscator=y #EndRegion;**** Directives created by AutoIt3Wrapper_GUI **** #include <Misc.au3> _Singleton("Test Utility") If Not IsArray($CmdLine) Then MsgBox(32, "Alert", "Invalid Array") Exit EndIf If $CmdLine[0] = 0 Then MsgBox(32, "Alert", "Invalid request") Exit EndIf $request = $CmdLine[1]; capture the parameter immediately Exit; Exit is included to isolate problem ; Normally, the script's processing starts here ; using parameters passed by calling application I wanted to try one last time to reach a conclusion on what I've observed. If anyone has a few minutes, I would greatly appreciate an independent confirmation of the results. Thanks for any help. The error is caused by obfuscated dllcalls in _Singleton when they are called in quick succession. I used this to reproduce the problem you have been talking about for $n = 1 to 20 run("temp-31.exe");temp-31 is the script you asked people to test sleep(50) Next and saw the errors you reported. Then I tried this #NoTrayIcon #Region;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Run_Obfuscator=y #EndRegion;**** Directives created by AutoIt3Wrapper_GUI **** #include <Misc.au3> _Singleton("Test Utility") sleep(400) and got exactly the same errors. However, if I do not compile obfuscated then I can run the test script even without the sleep(5) and the errors do not occur. If I replace _Singleton("Test Utility") with if _MutexExists("Test Utility") then exit Func _MutexExists($sOccurenceName) Local $ERROR_ALREADY_EXISTS = 183, $handle, $lastError $sOccurenceName = StringReplace($sOccurenceName, "\", ""); to avoid error $handle = DllCall("kernel32.dll", "int", "CreateMutex", "int", 0, "long", 1, "str", $sOccurenceName) $lastError = DllCall("kernel32.dll", "int", "GetLastError") Return $lastError[0] = $ERROR_ALREADY_EXISTS EndFunc I still get the error when the script is obfuscated if I call the exe faster than 10 times a second. As long as I leave one of the dllcalls in the function I get the error. Possibly there is something which Jos could explain, but calling an AutoIt exe so many times so quickly is not something I would expect anyone to have to allow for. Edited August 12, 2008 by martin Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
qwert Posted August 12, 2008 Author Share Posted August 12, 2008 (edited) The error is caused by _Singleton because it is written without considering that the dllcalls could fail and presumably they fail. It has nothing to do with $CmdLine. The solution is to either ensure you don't call your function too rapidly or you make you own version of _Singleton to remove the problems.By "own version of _Singleton", do you simply mean checking with ProcessExists? Or something more complicated?Also, is it only coincidence that I have yet to see my unobfuscated versions fail? Is it possible that they're that much faster than obfuscated? BTW, my core conflict isn't with calling the same script too soon. I only worked up this example to catch the error. The true conflict is between two scripts that operate completely asynchronous to one another. In other words, when ScriptB executes, it doesn't know where ScriptA is in its processing -- which led me to suspect some kind with interference in command line parameters in shared AutoIt processes or memory areas.I'd certainly like to know your opinion on these points. Thanks for your help.P.S. I just saw your additions to your post and am working through them. Thanks. Edited August 12, 2008 by qwert Link to comment Share on other sites More sharing options...
qwert Posted August 13, 2008 Author Share Posted August 13, 2008 my core conflict isn't with calling the same script too soon. I only worked up this example to catch the error. The true conflict is between two scripts that operate completely asynchronous to one another. In other words, when ScriptB executes, it doesn't know where ScriptA is in its processing -- which led me to suspect some kind with interference in command line parameters in shared AutoIt processes or memory areas."However, if I do not compile obfuscated then I can run the test script even without the sleep(5) and the errors do not occur.""I still get the error when the script is obfuscated if I call the exe faster than 10 times a second. As long as I leave one of the dllcalls in the function I get the error."Martin, thanks. Those results seem to confirm what I've been seeing.So I guess I'm ready to make this summarizing statement:Obfuscated scripts that receive parameters and that contain dllCalls are prone to the "Line -1 Error: Array..." if they are "hit" at a certain point in their processing by another script of the same fundamental type (command line parameters and dllCalls).Any comments? Is anyone aware of a valid processing condition that might explain this circumstance? Link to comment Share on other sites More sharing options...
martin Posted August 13, 2008 Share Posted August 13, 2008 Martin, thanks. Those results seem to confirm what I've been seeing.So I guess I'm ready to make this summarizing statement:Obfuscated scripts that receive parameters and that contain dllCalls are prone to the "Line -1 Error: Array..." if they are "hit" at a certain point in their processing by another script of the same fundamental type (command line parameters and dllCalls).Any comments? Is anyone aware of a valid processing condition that might explain this circumstance?My test didn't call the exe with parameters so the parameters are not relevant as far as I can tell.All I can say at the moment is that running 2 compiled obfuscated scripts in rapid succession will cause a crash with " "Line -1 Error: Array..." if they both make dllcalls as in the example.But you need to make some more tests to see if both have to be obfuscated or just one. Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. 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