Solved vbs script not starting from bacth file

September 21, 2015 at 07:32:18
Specs: Windows 7
I am working on a batch file which has VB Script to start where it activates an application, sends a password to that application and minimizes the application. My script fails sending the keys. The application does not get the password, but when I double-click on the script it receives the password and minimizes. I don't know where the error is .

InitliszeUSb.bat



START %myDrive%"RunSanDiskSecureAccess_Win.exe" 
pushd %~dp0
"" cscript "C:\Users\kiranv.EXCEL\Documents\Visual Studio 2010\Projects\ANPR \script\min.vbs"
 
    endlocal
START "%programfiles%\Mozilla Firefox\firefox.exe" "http://localhost/anpr/third.html" 
exit


Min.vbs:

Option Explicit
Dim oSHL : Set oSHL = CreateObject("WScript.Shell")
oSHL.AppActivate "SanDisk SecureAccess"
oSHL.SendKeys "pass1_word~" 'Enters Password
WScript.Sleep(3000)
oSHL.SendKeys "% n" 'Minimises the window
WScript.Quit

message edited by kiranv5


See More: vbs script not starting from bacth file

Report •


✔ Best Answer
September 21, 2015 at 20:31:13
Sendkeys can be finicky. (It should always be a "last resort") .I don't think you can send keys to a minimized or hidden window. So number one: first try using the START /MAX option. My experience is: If you can't see the window on your screen, sendkeys probably can't either.
Since the window accepts the password as soon as you maximize it tends to make me think this is the case here.
"The AppActivate method returns a Boolean value that identifies whether the procedure call is successful. This method changes the focus to the named application or window, but it does not affect whether it is maximized or minimized."
So if your "START" for some reason starts the app minimized, sendkeys will probably fail. If the app is slow to load/start, a simple loop (based on the boolean value mentioned above) will determine when the window is available. Exit the loop with a "fail" after a few hundred-thousand tries, or less tries and more sleeps.
Here's a utility I made to interface batch to sendkeys function in both vbs and vis-basic, eliminating some of the mess when cross-pollinating batch with Oop.

'-------- vis basic - "old"
Attribute VB_Name = "Module1"
Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
'"Sleep" IS VERY MUCH CASE SENSITIVE!!!
Sub main()
'verion 11.0731
'made some fixes, added the commandline option
'to override file "control", removed doevents
'from the delay for-loop
'NEWEST version sort-of fixes the control-key
'bug: ^ does not work, so the program sends the
'actual value of the control-char (f/e: ^A sends
'chr(1), unquoted, which i would not have guessed
'would work.)
'experimenting with new format: raw unquoted number
'is delay, anything else is data. see comment
fil = Command
On Error GoTo nono
If LTrim(fil) = "" Then fil = "control"
xx = "no file: " + fil
Open fil For Input As #1
xx = ""
Line Input #1, pgm
Line Input #1, signal
Line Input #1, windo
If signal = "" Then signal = 1
If pgm <> "" Then
pid = Shell(pgm, signal)
'windo = pid
'Print #6, "task id# is:"; pid
'Debug.Print pid
End If
'Debug.Print windo
j = 0
xx = "window not avail: " + windo
On Error GoTo 9
'7 For i = 1 To 4000: DoEvents: Next i
7 Sleep 200
AppActivate windo
GoTo 8
9 j = j + 1
If j > 200 Then GoTo nono
Resume 7
8 xx = "possible control file syntax error"
On Error GoTo 0
'for my diagnostics: report no. of tries needed
'If j > 0 Then Print #6, j; " tries"
Do While Not EOF(1)
'should i use "line input" here? might screw the quotes handling though.
Input #1, k
'here is where it discriminates between a "raw
'number" and a quoted number or any other data.
'raw numbers MUST be put in unquoted! else they are
'interpreted as data. the "on error" is req. to
'elimintate an error-trap when trying to add zero
'to non-numeric data.
If VarType(k) = vbInteger Or VarType(k) = vbLong Then
'any numeric integer is delay number. might need to adjust multiplier below
'41 is almost perfect for millsecs interpretation
'k = k * 41
'tt = Timer
'Debug.Print "k is a delay value "; k; " "; Timer
Sleep k
'Had to quit using the "sleep" - no longer supported.
'went back to the for-loop using doevents (doevents
'might be a mistake, testing...). The above factor
'of 41 is almost exactly right for milliseconds
'For i = 1 To k: DoEvents: Next i
'swapped out doevents - it seems to screw things up
'For i = 1 To k: Next i
Debug.Print Timer
Debug.Print Timer - tt
'End
Else
'Debug.Print "k: " + k
'Debug.Print "k is: " + k
'newest version control-bug-fix here: take out for winXP application!
'If Left(k, 1) = "^" Then
'x = Asc(UCase(Mid(k, 2))) - 64
'k = Chr(x)
'Debug.Print "k is chr of " + Str(x)
'End If
SendKeys k, True
Debug.Print k
End If
102
Loop
clstop:
'Debug.Print "done."
Close
End

nono:
Debug.Print Err
'Stop
'always use NON-interactive error-reporting!
'Close
If Err > 0 Then
If Err = 5 Then
'"invalid procedure call", assumed to be appactiv failure
s = "WINDOW-TITLE " + Chr(34) + windo + Chr(34) + " not available"
Else
s = Err.Description
End If
s = "***** ERROR #" + Str$(Err) + ": " + s
s = s + Chr(13) + Chr(10) + xx + Chr(13) + Chr(10)
's = s + "to view help file: sendkey /?"
'tst = MsgBox(s, 324)
'Clipboard.SetText s
Resume ff
End If
ff:
Close
End
End Sub
::------- I know; OVERKILL to the MAX.
here's vbscript:
'--- begin vbscript
set fso=createobject("scripting.filesystemobject")
set w=createobject("wscript.shell")
on error resume next
fil=wscript.arguments(0)
if err.number>0 then
fil="?"
err.clear
end if
on error goto 0
If Right(RTrim(fil), 1) = "?" Then
set c=fso.opentextfile("sendkey.doc",1)
a=0
do while not c.atendofstream
wscript.stdout.writeline c.readline
a=a+1
if a mod 23 = 0 then aa=wscript.stdin.readline
loop
wscript.echo "(content found in: sendkey.hlp)"
end if

set c=fso.opentextfile(fil,1)
pgm=c.readline
mode=c.readline
if mode="" then mode=1
windo=c.readline
if pgm <> "" then z=w.run (pgm,mode) :wscript.sleep 2000
wscript.echo pgm+" "+mode+" "+windo

if windo<>"" then w.appactivate windo
do while not c.atendofstream
x=c.readline
'wscript.echo "x"&x
send=x
'call numbtest x
if left(send,1)=chr(34) and right(send,1)=chr(34) then
send=mid(send,2,len(send)-2)
x=0
else
call numtest(x)
end if
if x>0 then
wscript.sleep x
else
'wscript.echo send
'only ONE right-hand space is trimmed, to allow for sending of right-spaces
'to send right spaces, append one extra space to account for this.
'this is done to allow integers to be sent without quoting them (so they
'won't be interpreted as delays.)
if right(send,1)=" " then send=left(send,len(send)-1)
w.sendkeys send,true
end if
loop
wscript.quit

sub numtest(x)
s=cstr(x)
if isnumeric(x) and left(s,1)<>"0" and instr(s,".")=0 then
x=cint(x)
if vartype(x)<2 or vartype(x)>3 then x=0
else
x=0
end if
if left(x,1)=" " then x=0
end sub
'------- end
helpfile:
Usage: sendkey [path+file]
If the path/filename is not given, then a default name of "control" will be tried.
The given file provides the script that drives the program.
The file's format consists of 3 leading or "header" elements, followed by
any number of data elements. Any element, whether header or data, is optional,
none are required, BUT you must reserve an empty spot for each header element.
Elements are separated by newline (each on its own line).
- CONTROL/SCRIPT FILE FORMAT -
HEADER:
1) program to start/run, incl. any commandline data: f/e: NOTEPAD SENDKEY.HLP
2) program window style: 0: hidden, 1: normal 2: icon 3: maximized
note: if window-style is zero, the window cannot be accessed for sendkey
3) title of window to which keys will be sent, matches any window up to
length of string given so be specific enough to get the right one.
f/e: sendkey - Notepad
DATA (SCRIPT):
4...) DATA: keystrokes and delays, mixed/assorted as needed:
Any unquoted integer is interpreted as a DELAY element in milliseconds
Keystroke(s): Any quoted item or non-integer item (quoted or not) is interpreted
as a keystroke-string to send. For more detail, refer to "KEYS" below.
Any item that contains a comma, be sure to enclose it in dbl quotes, like: ","
To send a dbl quote, enclose it in braces, like: {"}
Note: Some combinations, such as and especially, shift+tab, or: +{tab} will
fail unless quoted. To send a shifttab: "+{tab}"

Example: say you want to send the word "testing", then ENTER (newline),
then "line, two", a quoted "goodbye", then a 1-sec. delay, then alt-e,a (Select
All) into Notepad, this would be the content of the send-script file:
notepad
1
Untitled - Note
testing
{enter}
"line, two"
{ENTER}
{"}
goodbye
{"}
400
%e
a

Your batch can build the script file, since it's text, and then it can execute
the file (f/e: TEST): cscript sendkey.vbs test
NOTE: if you use batch to build the send-script, and you intend to send ALT
keys, be sure to double up the percents: >>TEST echo %%f (ALT-F)
(A sample file similar to this is included with the documentation: It does
write to a file "sendkey.xxx" in windows' temp directory
and also puts the content onto the clipboard using ctrl-C. The sample is called
"sendkey.tst" and demonstrates various keystrokes and actions.)

KEYS:
Nothing is sent into the window except exactly what you specify in the list.
When the end of the list is reached, control reverts to manual (user interactive).
"regular" keys are standard printable keys other than (){}[]^%+
Specify any regular keys like (examples): A, AB, AB76, A:B, A/?X&
The plus sign (+), caret (^), percent sign (%), tilde (~), and parentheses ( )
have special meanings to SendKeys. To specify one of these characters,
enclose it within braces. For example, to specify the plus sign, use {+}.
To send brace characters, use {{} and {}}.
Brackets ([ ]) must also be enclosed in braces as well, because some other
applications use them.

To specify characters that aren't displayed when you press a key (such as
ENTER or TAB) and keys that represent actions rather than characters, use the
following table: (note, these are NOT case sensitive)

Key Code
--------------------------------
BACKSPACE {BACKSPACE}, {BS}, or {BKSP}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
DEL {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER {ENTER} or ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS {INSERT}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
F1..F16 {F1}..{F16}
To specify keys combined with any combination of the SHIFT, CTRL, and ALT,
precede the regular key code with one or more of the following codes:
+ = SHIFT, ^ = CTRL, % = ALT. F/e: %{f4} for the end-pgm seq ALT-F4

To specify that any combination of SHIFT, CTRL, and ALT should be held down
while several other keys are pressed, enclose the code for those keys in
parentheses.
F/e, to send SHIFT-EC (SHIFT held down while E and C are pressed), use: +(EC)
To specify to hold down SHIFT while E is pressed, followed by C without SHIFT,
use: +EC
To specify repeating keys, use the form: {key number}. You must put a space
between key and number. For example, {LEFT 42} means press the LEFT ARROW key
42 times; {h 10} means press h 10 times.

SendKeys can't send keystrokes to an application that's not designed to run in
Windows. Sendkeys can't send the PRINT SCREEN (PRTSC) key to any application.

message edited by nbrane



#1
September 21, 2015 at 07:43:13
Check the return value of your AppActivate. Your script is probably running faster than your application's load.

How To Ask Questions The Smart Way


Report •

#2
September 21, 2015 at 07:50:12
While you are waiting for a real programmer to come along, I believe that after a START command the first thing between quotes is seen as a title. You could therefore try putting "" after the appropriate START to see if that helps.

EDIT:
Oops, I overlapped with a real programmer.

Always pop back and let us know the outcome - thanks

message edited by Derek


Report •

#3
September 21, 2015 at 08:18:57
HI Razor I tried to sleep the app after activate (for 3000) but nothing happens the application is active but not keys are passed.

Report •

Related Solutions

#4
September 21, 2015 at 09:37:48
I'm not sure 3 seconds is enough. I'd probably try something like this:
Option Explicit
Dim oSHL : Set oSHL = CreateObject("WScript.Shell")
Dim sleepCount
Do Until (oSHL.AppActivate("SanDisk SecureAccess") Or sleepCount >= 20)
  WScript.Sleep(3000) '20 * 3000ms = 60 seconds-ish
  sleepCount = sleepCount + 1
Loop
If (sleepCount < 20) Then
  oSHL.SendKeys "pass1_word~" 'Enters Password
  WScript.Sleep(3000)
  oSHL.SendKeys "% n" 'Minimises the window
Else
  MsgBox "AppActivate failed"
End If

How To Ask Questions The Smart Way


Report •

#5
September 21, 2015 at 20:31:13
✔ Best Answer
Sendkeys can be finicky. (It should always be a "last resort") .I don't think you can send keys to a minimized or hidden window. So number one: first try using the START /MAX option. My experience is: If you can't see the window on your screen, sendkeys probably can't either.
Since the window accepts the password as soon as you maximize it tends to make me think this is the case here.
"The AppActivate method returns a Boolean value that identifies whether the procedure call is successful. This method changes the focus to the named application or window, but it does not affect whether it is maximized or minimized."
So if your "START" for some reason starts the app minimized, sendkeys will probably fail. If the app is slow to load/start, a simple loop (based on the boolean value mentioned above) will determine when the window is available. Exit the loop with a "fail" after a few hundred-thousand tries, or less tries and more sleeps.
Here's a utility I made to interface batch to sendkeys function in both vbs and vis-basic, eliminating some of the mess when cross-pollinating batch with Oop.

'-------- vis basic - "old"
Attribute VB_Name = "Module1"
Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
'"Sleep" IS VERY MUCH CASE SENSITIVE!!!
Sub main()
'verion 11.0731
'made some fixes, added the commandline option
'to override file "control", removed doevents
'from the delay for-loop
'NEWEST version sort-of fixes the control-key
'bug: ^ does not work, so the program sends the
'actual value of the control-char (f/e: ^A sends
'chr(1), unquoted, which i would not have guessed
'would work.)
'experimenting with new format: raw unquoted number
'is delay, anything else is data. see comment
fil = Command
On Error GoTo nono
If LTrim(fil) = "" Then fil = "control"
xx = "no file: " + fil
Open fil For Input As #1
xx = ""
Line Input #1, pgm
Line Input #1, signal
Line Input #1, windo
If signal = "" Then signal = 1
If pgm <> "" Then
pid = Shell(pgm, signal)
'windo = pid
'Print #6, "task id# is:"; pid
'Debug.Print pid
End If
'Debug.Print windo
j = 0
xx = "window not avail: " + windo
On Error GoTo 9
'7 For i = 1 To 4000: DoEvents: Next i
7 Sleep 200
AppActivate windo
GoTo 8
9 j = j + 1
If j > 200 Then GoTo nono
Resume 7
8 xx = "possible control file syntax error"
On Error GoTo 0
'for my diagnostics: report no. of tries needed
'If j > 0 Then Print #6, j; " tries"
Do While Not EOF(1)
'should i use "line input" here? might screw the quotes handling though.
Input #1, k
'here is where it discriminates between a "raw
'number" and a quoted number or any other data.
'raw numbers MUST be put in unquoted! else they are
'interpreted as data. the "on error" is req. to
'elimintate an error-trap when trying to add zero
'to non-numeric data.
If VarType(k) = vbInteger Or VarType(k) = vbLong Then
'any numeric integer is delay number. might need to adjust multiplier below
'41 is almost perfect for millsecs interpretation
'k = k * 41
'tt = Timer
'Debug.Print "k is a delay value "; k; " "; Timer
Sleep k
'Had to quit using the "sleep" - no longer supported.
'went back to the for-loop using doevents (doevents
'might be a mistake, testing...). The above factor
'of 41 is almost exactly right for milliseconds
'For i = 1 To k: DoEvents: Next i
'swapped out doevents - it seems to screw things up
'For i = 1 To k: Next i
Debug.Print Timer
Debug.Print Timer - tt
'End
Else
'Debug.Print "k: " + k
'Debug.Print "k is: " + k
'newest version control-bug-fix here: take out for winXP application!
'If Left(k, 1) = "^" Then
'x = Asc(UCase(Mid(k, 2))) - 64
'k = Chr(x)
'Debug.Print "k is chr of " + Str(x)
'End If
SendKeys k, True
Debug.Print k
End If
102
Loop
clstop:
'Debug.Print "done."
Close
End

nono:
Debug.Print Err
'Stop
'always use NON-interactive error-reporting!
'Close
If Err > 0 Then
If Err = 5 Then
'"invalid procedure call", assumed to be appactiv failure
s = "WINDOW-TITLE " + Chr(34) + windo + Chr(34) + " not available"
Else
s = Err.Description
End If
s = "***** ERROR #" + Str$(Err) + ": " + s
s = s + Chr(13) + Chr(10) + xx + Chr(13) + Chr(10)
's = s + "to view help file: sendkey /?"
'tst = MsgBox(s, 324)
'Clipboard.SetText s
Resume ff
End If
ff:
Close
End
End Sub
::------- I know; OVERKILL to the MAX.
here's vbscript:
'--- begin vbscript
set fso=createobject("scripting.filesystemobject")
set w=createobject("wscript.shell")
on error resume next
fil=wscript.arguments(0)
if err.number>0 then
fil="?"
err.clear
end if
on error goto 0
If Right(RTrim(fil), 1) = "?" Then
set c=fso.opentextfile("sendkey.doc",1)
a=0
do while not c.atendofstream
wscript.stdout.writeline c.readline
a=a+1
if a mod 23 = 0 then aa=wscript.stdin.readline
loop
wscript.echo "(content found in: sendkey.hlp)"
end if

set c=fso.opentextfile(fil,1)
pgm=c.readline
mode=c.readline
if mode="" then mode=1
windo=c.readline
if pgm <> "" then z=w.run (pgm,mode) :wscript.sleep 2000
wscript.echo pgm+" "+mode+" "+windo

if windo<>"" then w.appactivate windo
do while not c.atendofstream
x=c.readline
'wscript.echo "x"&x
send=x
'call numbtest x
if left(send,1)=chr(34) and right(send,1)=chr(34) then
send=mid(send,2,len(send)-2)
x=0
else
call numtest(x)
end if
if x>0 then
wscript.sleep x
else
'wscript.echo send
'only ONE right-hand space is trimmed, to allow for sending of right-spaces
'to send right spaces, append one extra space to account for this.
'this is done to allow integers to be sent without quoting them (so they
'won't be interpreted as delays.)
if right(send,1)=" " then send=left(send,len(send)-1)
w.sendkeys send,true
end if
loop
wscript.quit

sub numtest(x)
s=cstr(x)
if isnumeric(x) and left(s,1)<>"0" and instr(s,".")=0 then
x=cint(x)
if vartype(x)<2 or vartype(x)>3 then x=0
else
x=0
end if
if left(x,1)=" " then x=0
end sub
'------- end
helpfile:
Usage: sendkey [path+file]
If the path/filename is not given, then a default name of "control" will be tried.
The given file provides the script that drives the program.
The file's format consists of 3 leading or "header" elements, followed by
any number of data elements. Any element, whether header or data, is optional,
none are required, BUT you must reserve an empty spot for each header element.
Elements are separated by newline (each on its own line).
- CONTROL/SCRIPT FILE FORMAT -
HEADER:
1) program to start/run, incl. any commandline data: f/e: NOTEPAD SENDKEY.HLP
2) program window style: 0: hidden, 1: normal 2: icon 3: maximized
note: if window-style is zero, the window cannot be accessed for sendkey
3) title of window to which keys will be sent, matches any window up to
length of string given so be specific enough to get the right one.
f/e: sendkey - Notepad
DATA (SCRIPT):
4...) DATA: keystrokes and delays, mixed/assorted as needed:
Any unquoted integer is interpreted as a DELAY element in milliseconds
Keystroke(s): Any quoted item or non-integer item (quoted or not) is interpreted
as a keystroke-string to send. For more detail, refer to "KEYS" below.
Any item that contains a comma, be sure to enclose it in dbl quotes, like: ","
To send a dbl quote, enclose it in braces, like: {"}
Note: Some combinations, such as and especially, shift+tab, or: +{tab} will
fail unless quoted. To send a shifttab: "+{tab}"

Example: say you want to send the word "testing", then ENTER (newline),
then "line, two", a quoted "goodbye", then a 1-sec. delay, then alt-e,a (Select
All) into Notepad, this would be the content of the send-script file:
notepad
1
Untitled - Note
testing
{enter}
"line, two"
{ENTER}
{"}
goodbye
{"}
400
%e
a

Your batch can build the script file, since it's text, and then it can execute
the file (f/e: TEST): cscript sendkey.vbs test
NOTE: if you use batch to build the send-script, and you intend to send ALT
keys, be sure to double up the percents: >>TEST echo %%f (ALT-F)
(A sample file similar to this is included with the documentation: It does
write to a file "sendkey.xxx" in windows' temp directory
and also puts the content onto the clipboard using ctrl-C. The sample is called
"sendkey.tst" and demonstrates various keystrokes and actions.)

KEYS:
Nothing is sent into the window except exactly what you specify in the list.
When the end of the list is reached, control reverts to manual (user interactive).
"regular" keys are standard printable keys other than (){}[]^%+
Specify any regular keys like (examples): A, AB, AB76, A:B, A/?X&
The plus sign (+), caret (^), percent sign (%), tilde (~), and parentheses ( )
have special meanings to SendKeys. To specify one of these characters,
enclose it within braces. For example, to specify the plus sign, use {+}.
To send brace characters, use {{} and {}}.
Brackets ([ ]) must also be enclosed in braces as well, because some other
applications use them.

To specify characters that aren't displayed when you press a key (such as
ENTER or TAB) and keys that represent actions rather than characters, use the
following table: (note, these are NOT case sensitive)

Key Code
--------------------------------
BACKSPACE {BACKSPACE}, {BS}, or {BKSP}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
DEL {DELETE} or {DEL}
DOWN ARROW {DOWN}
END {END}
ENTER {ENTER} or ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS {INSERT}
LEFT ARROW {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}
RIGHT ARROW {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW {UP}
F1..F16 {F1}..{F16}
To specify keys combined with any combination of the SHIFT, CTRL, and ALT,
precede the regular key code with one or more of the following codes:
+ = SHIFT, ^ = CTRL, % = ALT. F/e: %{f4} for the end-pgm seq ALT-F4

To specify that any combination of SHIFT, CTRL, and ALT should be held down
while several other keys are pressed, enclose the code for those keys in
parentheses.
F/e, to send SHIFT-EC (SHIFT held down while E and C are pressed), use: +(EC)
To specify to hold down SHIFT while E is pressed, followed by C without SHIFT,
use: +EC
To specify repeating keys, use the form: {key number}. You must put a space
between key and number. For example, {LEFT 42} means press the LEFT ARROW key
42 times; {h 10} means press h 10 times.

SendKeys can't send keystrokes to an application that's not designed to run in
Windows. Sendkeys can't send the PRINT SCREEN (PRTSC) key to any application.

message edited by nbrane


Report •


Ask Question