Working with a .exe file

M

Marco

Hi all,

I have a software ending with .exe that i would like to open, type
the
word 'select' on it, press 'enter' and make it run.


I used the following code :


wb = Shell("Y:\Programs\Sel.exe", 1)
Application.Wait Now() + TimeValue("00:00:15")

SendKeys "select"
SendKeys "{ENTER}"

but the Sel.exe either copies the text "select" on my vbe editor
or shows the text "select" but it doesn't
recognize it.
When I open Sel.exe and I type "select" + "{ENTER}", without using vba
code,it works.

Any helps?


Thanks,
Marco
 
N

NickHK

Marco,
If you must post to more than one NG, cross-post, not multi-post.
And stick to one thread.
You now have 4 threads in 2 NGs on the same subject, with replies but no
feedback from you.

NickHK
 
R

RB Smissaert

I think the trouble might be that Shell doesn't wait till the .exe is fully
launched, so
your next code line doesn't target the .exe.
Try to launch your .exe with this code:


Option Explicit
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type

Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessID As Long
dwThreadId As Long
End Type

Private Declare Function WaitForSingleObject _
Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As
Long

Private Declare Function CreateProcessA _
Lib "kernel32" (ByVal lpApplicationName As String,
_
ByVal lpCommandLine As String, _
ByVal lpProcessAttributes As Long,
_
ByVal lpThreadAttributes As Long,
_
ByVal bInheritHandles As Long, _
ByVal dwCreationFlags As Long, _
ByVal lpEnvironment As Long, _
ByVal lpCurrentDirectory As
String, _
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As
PROCESS_INFORMATION) As Long

Private Declare Function GetExitCodeProcess _
Lib "kernel32" (ByVal hProcess As Long, _
lpExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Private Const NORMAL_PRIORITY_CLASS = 32


Sub test()

'experiment with the 1000 as you may need less or even 0
ExecCmd "C:\WINDOWS\SYSTEM32\notepad.exe", 1000, True

End Sub


Function ExecCmd(sCmdLine As String, _
lmSecsWait As Long, _
Optional bShowWindow As Boolean) As Long

'will start an external process and
'wait till this process is finished
'returns > -1 if successfull and -1 if not
'-----------------------------------------
Dim proc As PROCESS_INFORMATION
Dim Start As STARTUPINFO
Dim lReturn As Long

'Initialize the STARTUPINFO structure:
With Start
.cb = Len(Start)
.dwFlags = 1 'hexadecimal would be &H1
If bShowWindow Then
.wShowWindow = 1
End If
End With

'Start the shelled application:
lReturn = CreateProcessA(sCmdLine, _
vbNullString, _
0, _
0, _
1, _
NORMAL_PRIORITY_CLASS, _
0, _
vbNullString, _
Start, _
proc)

'Wait for the shelled application to finish:
lReturn = WaitForSingleObject(proc.hProcess, lmSecsWait)
GetExitCodeProcess proc.hProcess, lReturn
CloseHandle proc.hThread
CloseHandle proc.hProcess
ExecCmd = lReturn

End Function


RBS
 
M

Marco

Thanks RBS but the problem still remains.
Your code is great in the sense that the text I want to type in
the .exe file is typed in correctly but when it executes by the
SendKeys "{ENTER}",
it gives an error message.
In the case I let the vba code open the file and then it is me to
enter "select + "{ENTER}", the .exe file still doesn't work.
In the case I open the file normally without vba code and i type in
"select + "{ENTER}" it works properly.

i'm really confused !!!??!!


Option Explicit
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type


Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessID As Long
dwThreadId As Long
End Type


Private Declare Function WaitForSingleObject _
Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long

Private Declare Function CreateProcessA _
Lib "kernel32" (ByVal lpApplicationName As String, _
ByVal lpCommandLine As String, _
ByVal lpProcessAttributes As Long, _
ByVal lpThreadAttributes As Long, _
ByVal bInheritHandles As Long, _
ByVal dwCreationFlags As Long, _
ByVal lpEnvironment As Long, _
ByVal lpCurrentDirectory As String, _
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION) As Long


Private Declare Function GetExitCodeProcess _
Lib "kernel32" (ByVal hProcess As Long, _
lpExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Private Const NORMAL_PRIORITY_CLASS = 32


Sub test()


'experiment with the 1000 as you may need less or even 0
ExecCmd "Y:\Programs\Sel.exe", 100000, True

End Sub



Function ExecCmd(sCmdLine As String, _
lmSecsWait As Long, _
Optional bShowWindow As Boolean) As Long


'will start an external process and
'wait till this process is finished
'returns > -1 if successfull and -1 if not
'-----------------------------------------
Dim proc As PROCESS_INFORMATION
Dim Start As STARTUPINFO
Dim lReturn As Long


'Initialize the STARTUPINFO structure:
With Start
.cb = Len(Start)
.dwFlags = 1 'hexadecimal would be &H1
If bShowWindow Then
.wShowWindow = 1
End If
End With


'Start the shelled application:
lReturn = CreateProcessA(sCmdLine, _
vbNullString, _
0, _
0, _
1, _
NORMAL_PRIORITY_CLASS, _
0, _
vbNullString, _
Start, _
proc)


'Wait for the shelled application to finish:
lReturn = WaitForSingleObject(proc.hProcess, lmSecsWait)
SendKeys "Select"
' SendKeys "{ENTER}"
GetExitCodeProcess proc.hProcess, lReturn
CloseHandle proc.hThread
CloseHandle proc.hProcess
ExecCmd = lReturn


End Function
 
R

RB Smissaert

it gives an error message.

What error message?
Maybe you need some other keystrokes to set the focus
on the right button in that app and only then send ENTER.

RBS
 
M

Marco

RBS,

the error is that it says that another file to which the .exe file is
linked to could not be found.

But when i type in the text "select" by keyboard it recognize it.

what i'm thinking is that maybe the font from excel vba is different
or that there is a sort of incompatibility between them.
 
M

Marco

I checked the compatibility of the .exe file by 'properties' and it is
blocked showing a compatibility for windows 95

Do you know any procedure to scan the .exe file?


thanks for your help.
Marco
 
R

RB Smissaert

Sorry, you I don't get you now.
Is there a button to be pressed and if so did you try moving the focus to
button?

RBS
 
M

Marco

there is not a button but it looks like a DOS window.
What i meant before was if you know any system to open the .exe file
and see how it works..
I think that is the only solution.

Marco
 
M

Marco

Thinking better i had an idea.

The .exe file elaborates other 2 text files stored in the same
directory of the .exe file.
The problem is that when I open it by vba, it doesn't recognize the
other 2 files.
So what I supposed is that when I open it by vba, vba locates the .exe
file in an other directory from which the .exe file
can't find the other two files.

what do you think about?
 
R

RB Smissaert

Don't think you are on the right track there.

Have you tried this:

With Application
.SendKeys "select", True
.SendKeys "{ENTER}", True
End With

RBS
 
R

RB Smissaert

Another option is to avoid SendKeys and use the Windows API as there are
some bugs with SendKeys.

Try this one:

Put all this code in a Class module:

Option Explicit
Private Declare Function MapVirtualKey _
Lib "user32" _
Alias "MapVirtualKeyA" _
(ByVal wCode As Long, _
ByVal wMapType As Long) As Long
Private Declare Function VkKeyScan _
Lib "user32" _
Alias "VkKeyScanA" _
(ByVal cChar As Byte) As Long
Private Declare Sub keybd_event _
Lib "user32" _
(ByVal bVk As Byte, _
ByVal bScan As Byte, _
ByVal dwFlags As Long, _
ByVal dwExtraInfo As Long)
Private Declare Sub Sleep Lib "kernel32" _
(ByVal dwMilliseconds As Long)
Private Declare Function GetKeyState _
Lib "user32" _
(ByVal nVirtKey As Long) As Long
Private Declare Function SetKeyboardState _
Lib "user32" _
(lppbKeyState As Any) As Long

Private Const KEYEVENTF_EXTENDEDKEY = &H1
Private Const KEYEVENTF_KEYUP = &H2

Public Enum eKeys
keyBackspace = &H8
keyTab = &H9
keyReturn = &HD
keyShift = &H10
keyControl = &H11
keyAlt = &H12
keyPause = &H13
keyEscape = &H1B
keySpace = &H20
keyEnd = &H23
keyHome = &H24
keyLeft = &H25
KeyUp = &H26
keyRight = &H27
KeyDown = &H28
keyInsert = &H2D
keyDelete = &H2E
keyF1 = &H70
keyF2 = &H71
keyF3 = &H72
keyF4 = &H73
keyF5 = &H74
keyF6 = &H75
keyF7 = &H76
keyF8 = &H77
keyF9 = &H78
keyF10 = &H79
keyF11 = &H7A
keyF12 = &H7B
keyNumLock = &H90
keyScrollLock = &H91
keyCapsLock = &H14
End Enum

Public Enum eLockKey
CapsLock = keyCapsLock
NumLock = keyNumLock
ScrollLock = keyScrollLock
End Enum

Private zlKeyPressDelay As Long

'Purpose : Press a single key represented by a string
'Inputs : sKey The key to press.
' [bHoldKeydown] If True does not
'release the key press.
' [bRelease] If True releases a
'"HoldKeydown" key press (see above).
'Outputs : N/A
Public Sub SendKey(sKey As String, _
Optional bHoldKeydown As Boolean = False, _
Optional bRelease As Boolean = False)

Dim lScan As Long
Dim lExtended As Long
Dim lVK As Long
Dim bShift As Boolean
Dim bCtrl As Boolean
Dim bAlt As Boolean

lVK = VkKeyScan(Asc(sKey))

If lVK Then
lScan = MapVirtualKey(lVK, 2)
lExtended = 0
If lScan = 0 Then
lExtended = KEYEVENTF_EXTENDEDKEY
End If
lScan = MapVirtualKey(lVK, 0)

bShift = (lVK And &H100)
bCtrl = (lVK And &H200)
bAlt = (lVK And &H400)

lVK = (lVK And &HFF)

If bRelease = False Then
If bShift Then
keybd_event eKeys.keyShift, 0, 0, 0
End If
If bCtrl Then
keybd_event eKeys.keyControl, 0, 0, 0
End If
If bAlt Then
keybd_event eKeys.keyAlt, 0, 0, 0
End If
keybd_event lVK, lScan, lExtended, 0
End If

If bHoldKeydown = False Then
keybd_event lVK, lScan, KEYEVENTF_KEYUP Or lExtended, 0

If bShift Then
keybd_event eKeys.keyShift, 0, KEYEVENTF_KEYUP, 0
End If
If bCtrl Then
keybd_event eKeys.keyControl, 0, KEYEVENTF_KEYUP, 0
End If
If bAlt Then
keybd_event eKeys.keyAlt, 0, KEYEVENTF_KEYUP, 0
End If
End If
End If
End Sub

'Purpose : Loops through a string and calls SendKey for each character
'Inputs : sString The string to press.
' [bDoEvents] If True returns control to the
processor
'after every keypress.
'Outputs : N/A
Public Sub SendString(ByVal sString As String, _
Optional bDoEvents As Boolean = True)

Dim sKey As String * 1
Dim lKey As Long
Dim lLen As Long

lLen = Len(sString)

For lKey = 1 To lLen
sKey = Mid$(sString, lKey, 1)
SendKey sKey
Sleep zlKeyPressDelay
'----------------------------
'doesn't work with DoEvents '
'----------------------------
If bDoEvents Then
DoEvents
End If
Next

End Sub

'Purpose : Presses a virtual key (used for keys that don't have ascii
equilivant)
'Inputs : ekeyPress The virtual key to press
' [bHoldKeydown] If True does not release the key
press.
' [bRelease] If True releases the key press.
' [bCompatible]
'Outputs : N/A
Public Sub PressKeyVK(ekeyPress As eKeys, _
Optional bHoldKeydown As Boolean, _
Optional bRelease As Boolean, _
Optional bCompatible As Boolean)

Dim lScan As Long
Dim lExtended As Long

lScan = MapVirtualKey(ekeyPress, 2)
lExtended = 0
If lScan = 0 Then
lExtended = KEYEVENTF_EXTENDEDKEY
End If
lScan = MapVirtualKey(ekeyPress, 0)

If bCompatible Then
lExtended = 0
End If

If Not bRelease Then
keybd_event ekeyPress, lScan, lExtended, 0
End If

If Not bHoldKeydown Then
keybd_event ekeyPress, lScan, KEYEVENTF_KEYUP Or lExtended, 0
End If

End Sub

'Purpose : Sets the status of the various Lock keys
'Inputs : LockKey The lock key to set the status of.
'Outputs : N/A
Public Sub SetLockStatus(LockKey As eLockKey, bOn As Boolean)

Dim abKeys(0 To 256) As Byte

abKeys(LockKey) = (bOn * -1)
'Win 9x
Call SetKeyboardState(abKeys(0))

'GetKeyState returns 1 if OFF and 0 if ON
If GetKeyState(LockKey) <> IIf(bOn, 0, 1) Then
'Win NT
'Simulate Key Press
keybd_event LockKey, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0
'Simulate Key Release
keybd_event LockKey, &H45, KEYEVENTF_EXTENDEDKEY Or _
KEYEVENTF_KEYUP, 0
End If

End Sub

'Purpose : returns the status of the various Lock keys
'Inputs : LockKey The lock key to return the status of.
'Outputs : Returns True if the Lock status is on.
Public Function GetLockStatus(LockKey As eLockKey) As Boolean
GetLockStatus = GetKeyState(LockKey)
End Function

'Determines the delay between subsequent keystrokes in the SendString
routine
Property Get KeyPressDelay() As Long
KeyPressDelay = zlKeyPressDelay
End Property

Property Let KeyPressDelay(Value As Long)
zlKeyPressDelay = Value
End Property

Private Sub Class_Initialize()
zlKeyPressDelay = 20 'Add a delay of 20 ms between pressing each key
End Sub


Then in a normal module put this code:

Sub test()

Dim cSK As clsSendKeys

Set cSK = New clsSendKeys

cSK.SendString "select", False
cSK.PressKeyVK keyReturn

End Sub


See if that works.


RBS
 
N

NickHK

Marco,
You seem to have answered Karl's post in one of your other threads.
You have a console app, not a windowed app. Is that correct ?

Have you tried using the command line to send arguments ?
You need to check what this exe does and how it expects/supports input.

NickHK
 
M

Marco

Hi RBS,

i tried your new code but i got a following error on the line
'Dim cSK As clsSendKeys '

Compile error:
User-defined type not defined

thanks
Marco
 
R

RB Smissaert

You need to name the class module clsSendKeys.
Do this by selecting the class module on the left in the
project explorer, pressing F4 and then altering the name
in the name box on the right.

RBS
 
M

Marco

Hi NickHK,

my file is a console app.
what do you mean for 'Have you tried using the command line to send
arguments ?'
i tried both by vba and by keyboard and it works only if I open the
file normally and if I type "select" by keyboard

you say:
You need to check what this exe does and how it expects/supports
input.
the exe wants his three files in the same directory where the exe is
stored.
do I have any chance to see its underlying code?


Thanks,
Marco
 
N

NickHK

Marco,
This explains the command line approach:
http://en.wikipedia.org/wiki/Command_line_interface

Maybe you app will work with
wb = Shell("Y:\Programs\Sel.exe /SomeValue", 1)

But you need to check the documentation on this app or experiment more.
Don't keep saying a certain line does not work.
We have no idea what this app is/does.
You have to help yourself also.

NickHK
 
M

Marco

sorry about that but I'm not a guru of vba...

I succeeded in making it work...and I ensure you that I've never
thought that vba could do what you showed..

what unfortunately I have to say is that the problem still remains and
I'm going to repeat it as simple as I can without driving you mad.

the .exe file uses three other text files stored in the same directory
in which the .exe file is stored and it manipulates them creating a
text file as output.
What I have to do is just to type the name of the first part of the
three files' name (with the same root but different extension
e.g. "select" which has select.dat, select.con and select.tmp) and
press enter.
When I open it normally it works
When I let the vba code open it and after i type in as normally, it
says that it can't find the 'select.con'

Did I make it clear?
for any question feel free to ask

Marco
 
M

Marco

NickHK

thanks again for your help.
I tried the line you suggested but the error is about the path.
I will read what you say about the command line

about your following comments, maybe it looks strange that i can't
find a solution but i don't really know what is the problem..and where
I have to look up to solve it.

Marco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top