How to debug "Subscript used on non-accessible variable"? - autoit

This is my code:
#RequireAdmin
#Region Directives created by AutoIt3Wrapper_GUI
#AutoIt3Wrapper_UseX64=n
#EndRegion Directives created by AutoIt3Wrapper_GUI
ListDrives("REMOVABLE")
ListDrives("FIXED")
Func ListDrives($type)
$drive = DriveGetDrive($type)
For $i = 1 To $drive[0]
MsgBox(64,"",$drive[$i])
Next
EndFunc
The error is :
("C:\Users\Javad\Desktop\01.au3" (7) : ==> Subscript used on
non-accessible variable.:
For $i = 1 To $drive[0]
For $i = 1 To $drive^ ERROR)
How to debug "Subscript used on non-accessible variable"?

Maybe you drive is not removeable but CD-ROM.
Try this to have a look at your drives.
#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
$re = ListDrives($DT_ALL)
_ArrayDisplay($re, 'Drives and Drivetypes')
;~ ListDrives($DT_FIXED)
Func ListDrives($type)
Local $aArray = DriveGetDrive($type)
Local $drive_A[0][2]
If #error Then
; An error occurred when retrieving the drives.
MsgBox($MB_SYSTEMMODAL, "", "It appears an error occurred.")
Else
For $i = 1 To $aArray[0]
_ArrayAdd($drive_A, StringUpper($aArray[$i]) & '|' & DriveGetType($aArray[$i]))
Next
EndIf
Return $drive_A
EndFunc ;==>ListDrives

Related

File descriptors not properly passed to processes generated with execve() system call

I'm reading a unix book and specifically the part about execve() system call. The book says that file descriptors related to opened file are passed to child processes and also ( default behaviour ) after a process calls execve().
However, when I tried this code to read an opened file descriptor delivered to a process generated with execve() it doesn't seem to work. What's the problem ?
Program that calls execve() :
int main(int arg,char *argv[],char **env){
int fd;
if ( (fd = open("text.txt",O_RDWR | O_CREAT, ALL_OWNER )) == -1 ){
printf("Open failed\n");
exit(1);
};
printf("%d\n",fd); // 3
char buff [] = "Hello World\n";
write(fd,buff,strlen(buff));
int res;
if ( (res = execl("./demo",(char *)0)) == -1 ){
exit(1);
};
}
Program demo invoked by execve() :
setbuf(stdout,NULL);
printf("Demo executing...\n");
ssize_t r;
char buff[1024];
while ( (r = read(3,buff,sizeof(buff))) > 0 ){
write(STDOUT_FILENO,buff,r);
}
I'm using a Mac OS
The "demo" process inherit file descriptor and can read the file, but the file offset is at the end of the file. Use lseek(fd, 0, SEEK_SET) before calling execl(), or do it in "demo" before reading the file.

Why Function "if ProcessExist" Don't Work in Others Computers

I'm trying to execute an IF ProcessExist.
in my win 10 64bit computer it works, but when i execute in other PC with win 7 or even with win 10. It do not execute.
#AutoIt3Wrapper_UseX64=N
If ProcessExists ("program.exe") Then
MsgBox ("", "Hold", "Test", 10)
Exit
Else
#RequireAdmin
Run(#ComSpec & " /c " & "C:\folder\file.bat", "", #SW_HIDE)
EndIf
Keep getting as if program.exe exist, but it's not.
#RequireAdmin must be on the very top of your script.
I assume it's not working when you compile the executable. It's probably called program.exe and it's finding its own process.
As for the Singleton see this:
_Singleton ( $sOccurrenceName [, $iFlag = 0] )
Enforce a design paradigm where only one instance of the script may be running
Example
#include <Misc.au3>
#include <MsgBoxConstants.au3>
If _Singleton("test", 1) = 0 Then
MsgBox($MB_SYSTEMMODAL, "Warning", "An occurrence of test is already running")
Exit
EndIf
MsgBox($MB_SYSTEMMODAL, "OK", "the first occurrence of test is running")

Running Autoit from command line and see errors/results

I am trying to run some autoit.au3 script from command line and see results there. I have put some ConsoleWrite inside script and also Exit(1) but after I run script nothing is shown in console. It just stop script on Exit and ConsoleWrite is not displayed.
I have use command:
"C:...(path to my AutoIt3.exe)" /ErrorStdOut "path_to_my_script.au3"'
Also I have tried to run script.exe with this same command but with similar (no) result. I would like to see output in console and/or custom error messages when script fail (I don't know if that is possible).
AutoIt3.exe is a GUI program. So the STD streams of a GUI program are not printed at a console by default.
The /ErrorStdOut argument redirects errors messages to Console instead of a Msgbox.
This argument does not enable print at the Console.
Command Prompt:
To print at a Command Prompt, you could pipe to more, i.e.
"C:...(path to my AutoIt3.exe)" /ErrorStdOut "path_to_my_script.au3" 2>&1|more
more reads from the Stdin stream and prints to Console.
I intentionly added 2>&1 so the Stderr stream is merged with
Stdout so you get the merged streams printed.
If you do not want the errors, then you can redirect the Stderr stream to nul i.e.
replace 2>&1 with 2>nul.
If you used a for loop at a Command Prompt, it would be i.e.
for /f "delims=" %A in ('"C:...(path to my AutoIt3.exe)" /ErrorStdOut test1.au3') do echo %A
If you use the for loop in batch-file, use %%A instead of %A. To also capture the Stderr, insert 2^>&1 into the for command or to ignore, insert 2^>nulinto the for command i.e.
for /f "delims=" %A in ('2^>nul "C:...(path to my AutoIt3.exe)" /ErrorStdOut test1.au3') do echo %A
The previous methods will not get the Exitcode.
AutoIt code:
An AutoIt script can get the Stdout and the Exitcode.
#pragma compile(Out, 'consoleau3.exe')
#pragma compile(Console, True)
$sAutoit = 'C:...(path to my AutoIt3.exe)'
$iPid = Run('"' & $sAutoit & '" /ErrorStdout ' & $CMDLINERAW, '', #SW_SHOW, 2) ; 2 = Get Stdout stream.
If #error Then Exit
; Open process handle.
$hPid = _ProcessOpenHandle($iPid)
; Get Stdout stream and then print to Console.
$sStdout = ''
Do
Sleep(10)
If $sStdout Then ConsoleWrite($sStdout & #CRLF)
$sStdout = StdoutRead($iPid)
Until #error
; Require process to be closed before calling _ProcessGetExitCode()
ProcessWaitClose($iPid)
; Get exitcode of process.
$iExitcode = _ProcessGetExitCode($hPid)
; Close process handle.
_ProcessCloseHandle($hPid)
Exit $iExitcode
Func _ProcessOpenHandle($iPID)
; Get the process handle of the process to query\n Return: Success Handle as array. Failure 0
Local Const $PROCESS_QUERY_INFORMATION = 0x400
Local $hPID = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', $PROCESS_QUERY_INFORMATION, 'int', 0, 'int', $iPID)
If #error Then Return SetError(#error, #extended, 0)
Return $hPID[0]
EndFunc
Func _ProcessGetExitcode($hPID)
; Get exitcode of the closed process\n Return: Success Exitcode as integer. Failure 0
Local $vPlaceholder
$hPID = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $hPID, 'int*', $vPlaceholder)
If #error Then Return SetError(#error, #extended, 0)
Return $hPID[2]
EndFunc
Func _ProcessCloseHandle($hPID)
; Close the handle of a process\n Return: Success 1. Failure 0
DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $hPID)
If #error Then Return SetError(#error, #extended, 0)
Return 1
EndFunc
Correct the path to AutoIt.exe in the code.
Compile to AutoIt code to executable. It will be a Console program
and will be named consoleau3.exe as to the #pragma compile directives.
Usage:
consoleau3 "path_to_my_script.au3"
Script arguments can be added i.e.
consoleau3 "path_to_my_script.au3" arg1 arg2 arg3 ...

Click on the outlook calendar by searching the calendar Image (_ImageSearch)

I am using Imagesearch.au3 to search the calendar image on outlook . Below is the code .
Created a new folder --> ImageSearch.au3 , ImageSearchDLL.dll , and the screenshot of the calendar is placed
#include <ImageSearch.au3>
$x=0
$y=0
start()
while 1
sleep(1000)
WEnd
Func Start()
while 1
$result = _ImageSearch("cal.png",1,$x,$y,0)
if $result=1 Then
ConsoleWrite("Sucesfull")
MouseMove($x,$y,10)
Else
ConsoleWrite("Img not found")
EndIf
WEnd
EndFunc
Problem : Throws an error message
"C:\Users...\Desktop\AutoIT\New folder\img\ImageSearch.au3" (44) : ==> Subscript used on non-accessible variable.:
if $result[0]="0" then return 0
if $result^ ERROR
The dll will not load while running as a script. I'm not sure why but it seems others have the same problem. I was able to compile the script as a 64 bit application and then the application loaded the DLL. After changing the tolerance, I was able to find the image.
Also, I would rewrite your code. You have two infinite while loops for no reason. I added a sleep to the remain while loop. I would increase the tolerance.
#include <ImageSearch.au3>
start()
Func Start()
while 1
$x=0
$y=0
$result = _ImageSearch("cal.png",1,$x,$y,20)
if $result=1 Then
MsgBox(0,"Found Image","moving mouse")
MouseMove($x,$y,10)
Else
MsgBox(0,"Img not found","not found")
EndIf
sleep(10000)
WEnd
EndFunc
I tested with the 64bit imagesearch located at http://www.autoitscript.com/forum/topic/148005-imagesearch-usage-explanation/page-2

How do I determine if a terminal is color-capable?

I would like to change a program to automatically detect whether a terminal is color-capable or not, so when I run said program from within a non-color capable terminal (say M-x shell in (X)Emacs), color is automatically turned off.
I don't want to hardcode the program to detect TERM={emacs,dumb}.
I am thinking that termcap/terminfo should be able to help with this, but so far I've only managed to cobble together this (n)curses-using snippet of code, which fails badly when it can't find the terminal:
#include <stdlib.h>
#include <curses.h>
int main(void) {
int colors=0;
initscr();
start_color();
colors=has_colors() ? 1 : 0;
endwin();
printf(colors ? "YES\n" : "NO\n");
exit(0);
}
I.e. I get this:
$ gcc -Wall -lncurses -o hep hep.c
$ echo $TERM
xterm
$ ./hep
YES
$ export TERM=dumb
$ ./hep
NO
$ export TERM=emacs
$ ./hep
Error opening terminal: emacs.
$
which is... suboptimal.
A friend pointed me towards tput(1), and I cooked up this solution:
#!/bin/sh
# ack-wrapper - use tput to try and detect whether the terminal is
# color-capable, and call ack-grep accordingly.
OPTION='--nocolor'
COLORS=$(tput colors 2> /dev/null)
if [ $? = 0 ] && [ $COLORS -gt 2 ]; then
OPTION=''
fi
exec ack-grep $OPTION "$#"
which works for me. It would be great if I had a way to integrate it into ack, though.
You almost had it, except that you need to use the lower-level curses function setupterm instead of initscr. setupterm just performs enough initialization to read terminfo data, and if you pass in a pointer to an error result value (the last argument) it will return an error value instead of emitting error messages and exiting (the default behavior for initscr).
#include <stdlib.h>
#include <curses.h>
int main(void) {
char *term = getenv("TERM");
int erret = 0;
if (setupterm(NULL, 1, &erret) == ERR) {
char *errmsg = "unknown error";
switch (erret) {
case 1: errmsg = "terminal is hardcopy, cannot be used for curses applications"; break;
case 0: errmsg = "terminal could not be found, or not enough information for curses applications"; break;
case -1: errmsg = "terminfo entry could not be found"; break;
}
printf("Color support for terminal \"%s\" unknown (error %d: %s).\n", term, erret, errmsg);
exit(1);
}
bool colors = has_colors();
printf("Terminal \"%s\" %s colors.\n", term, colors ? "has" : "does not have");
return 0;
}
Additional information about using setupterm is available in the curs_terminfo(3X) man page (x-man-page://3x/curs_terminfo) and Writing Programs with NCURSES.
Look up the terminfo(5) entry for the terminal type and check the Co (max_colors) entry. That's how many colors the terminal supports.

Resources