Jump to content

Notes on "Line -1 Error: Array ... "


 Share

Recommended Posts

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.

post-29172-1217970545_thumb.png

Link to comment
Share on other sites

  • Moderators

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

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

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.html

It 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

Link to comment
Share on other sites

  • Moderators

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

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

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

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

  • Moderators

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

Although 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

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 time

2. Both scripts have parameters passed to them

3. 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

  • Moderators

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 time

2. Both scripts have parameters passed to them

3. 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 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

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 window

Call ScriptB (with parameters) to adjust contents of taskbar

My 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

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

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

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 application

Unobfuscated, 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

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

#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 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

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 by qwert
Link to comment
Share on other sites

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

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

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...