Solved

SENDKEYS Problem

Posted on 2003-11-06
18
1,360 Views
Last Modified: 2007-12-19
I am using SENDKEYS to manipulate an application that I have not been able to figure out how to get VB to interact with.  I hate SENDKEYS but was the best and only way to get it to work.

First question would be how to get VB to work with this program.

Second problem is as follows:

'Opens a file using a non VB application.

 1   Result = ShellExecute(0, "Open", "C:\Capacity Folder\TKS.psr", "", "", SW_SHOWNORMAL)
 2  
 3   Call Sleep(5000)
 4   SendKeys "%S" 'Alt+S to activate the "SAVE AS" button
 5   Call Sleep(5000)
 6   SendKeys "C:\Capacity Folder\TKS.txt" 'File name and location
 7   SendKeys "{ENTER}" 'Enter to save file
 8   Call Sleep(5000)
 9   SendKeys "Y"    'Yes to replace old file
10  Call Sleep(5000)
11  SendKeys "%{F4}"    'Close Application

I use the Call Sleep to try and pause and wait for the next window to appear.

The program get's all the way to the line 4 or 5 and skips the rest.  My guess was that the Sleep time wasn't enough time but if I increase the time, it still doesn't help.  I am looking for solutions or alternatives.

AJ
0
Comment
Question by:ajpelkey
  • 9
  • 5
  • 2
  • +2
18 Comments
 

Author Comment

by:ajpelkey
ID: 9694201
Also, the SENDKEYS has the following syntax:

SENDKEYS [STRING], [WAIT]

What is the [WAIT] used for?
0
 
LVL 28

Expert Comment

by:vinnyd79
ID: 9694277
It sounds like the window being called to enter a filename is a modal window,which means  your code will not continue until the window is closed.I don't think SendKeys will work for you.
0
 

Author Comment

by:ajpelkey
ID: 9694332
Thx Vinnyd79,

Can you explain "modal window".

Do you have any suggestions?

AJ
0
 
LVL 1

Expert Comment

by:KeyPakt
ID: 9694524
A modal window is a window like a message box. You can't continue with your code until you have clicked the Ok button. A window that is modal less this means that you can switch between this window and the window that you opened this window from.

Wait can either be true of false in the SendKeys command and means:
false (default) = after your "%S" has been sent the code immediately continues to the Call Sleep(5000) even if the place where you sent the "%S" has not been able to process these.
ture = code will continue only if the place where you sent the keys has processed the keys.

Basically this means that you can skip the Sleep command if you use sendkeys with Wait = true.
0
 

Author Comment

by:ajpelkey
ID: 9694568
I know if I use MacroAngel, I can specify which window to send the keystrokes to.  Is there a way to do that in VB.  Also, is there a way to determine the windows name.
0
 
LVL 1

Expert Comment

by:KeyPakt
ID: 9694674
Well. Since you use the ShellExecute and you recieve a Result - in your case it's called reuslt also :) - which means that you have a handle to the application you started. Using the AppActivate command like AppActivate Result (your handle) you have control of the application you started.

The handle returned from the ShellExecute command is valid for as long as you have not exited your code.
0
 
LVL 2

Accepted Solution

by:
wuttrain earned 315 total points
ID: 9694923
hi ajpelkey,

I've used notepad in this example.  first it opens c:\test.txt file, clicks on the Save As menu, types c:\test1.txt to the filename edit box, and clicks the Save button, then it clicks the Yes button when prompted to replace the old file. then it closes notepad. just be sure test.txt and test1.txt already exist in c:\

i hope this helps.

Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetDlgCtrlID Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Const WM_COMMAND = &H111
Const WM_SETTEXT = &HC
Const BN_CLICKED = 0
Private Const SW_SHOWNORMAL = 1


Private Sub Command1_Click()
  OpenAndSave
End Sub

Function OpenAndSave()
Dim hwndWord As Long
Dim tempHwnd As Long
Dim hMainMenu As Long
Dim hMenu As Long
Dim MenuID As Long
Dim lRet As Long
Dim strNewFilename As String
Dim hwndEdit As Long
Dim hwndButton As Long
Dim Button As Long
Dim ParentHwnd As Long
On Error GoTo ErrorHandler
 
  'open text file
  Result = ShellExecute(0, "Open", "c:\test.txt", "", "", SW_SHOWNORMAL)
 
  Sleep 2000 'needs a longer time
 
  hwndWord = FindWindow(vbNullString, "test.txt - Notepad")
  hMainMenu = GetMenu(hwndWord)
  hMenu = GetSubMenu(hMainMenu, 0)  'get into the File Menu 0
  MenuID = GetMenuItemID(hMenu, 3) 'select on Save As submenu
  lRet = PostMessage(hwndWord, WM_COMMAND, MenuID, 0&) 'send the command to click Save As submenu
  Sleep 2000 'or you can create a loop to check whether the save dialog box has loaded
 
 
  hwndWord = FindWindow(vbNullString, "Save As")  'get the save as window handle
  hwndEdit = FindWindowEx(hwndWord, 0, "Edit", vbNullString)  'get the edit box handle
  strNewFilename = "c:\test1.txt"
  lRet = SendMessage(hwndEdit, WM_SETTEXT, 0, ByVal strNewFilename) 'type the filename
 
 
  hwndButton = FindWindowEx(hwndWord, 0, "Button", "&Save") 'get the Save button handle
 
  'click the save button
  Button = GetDlgCtrlID(hwndButton)
  ParentHwnd = GetParent(hwndButton)
  lRet = PostMessage(ParentHwnd, WM_COMMAND, Button, BN_CLICKED * &H10000 + hwndButton)
 
  Sleep 2000
 
  'click yes button
  hwndWord = FindWindow(vbNullString, "Save As")  'get the save as window handle
  hwndButton = FindWindowEx(hwndWord, 0, "Button", "&Yes") 'get the Yes button handle
 
  Button = GetDlgCtrlID(hwndButton)
  ParentHwnd = GetParent(hwndButton)
  lRet = PostMessage(ParentHwnd, WM_COMMAND, Button, BN_CLICKED * &H10000 + hwndButton)

  'close application
 
  Sleep 2000
  hwndWord = FindWindow(vbNullString, "test1.txt - Notepad") 'using the new file name
  hMainMenu = GetMenu(hwndWord)
  hMenu = GetSubMenu(hMainMenu, 0)  'get into the File Menu 0
  MenuID = GetMenuItemID(hMenu, 8) 'select on Exit submenu
  lRet = PostMessage(hwndWord, WM_COMMAND, MenuID, 0&) 'send the command to click Exit submenu
 
  Exit Function
 
ErrorHandler:
  MsgBox Err.Number & ":" & Err.Description, vbCritical, "FUNC/OpenAndSave: Unknown error, application will be terminated."
  Exit Function
 
End Function

0
 

Author Comment

by:ajpelkey
ID: 9696219
wuttrain,
Your answer helped me more than you know.  I am now only using SendKeys once.  I think I can eliminate it but I need some help with a function.

I am looking at a window called CRDB PSR Viewer - [C:\CAPACITY FOLDER\TKS.PSR].  in the window, on the right hand side is a Button with Save As with S underlined (basically &Save As, I assume).  When I use the following code:

hwndWord = FindWindow(vbNullString, "CRDB PSR Viewer - [C:\CAPACITY FOLDER\TKS.PSR]")
hwndButton = FindWindowEx(hwndWord, 0, "Button", "&Save As")

hwndButton returns a value of 0.  It could not find the button.  I am not sure if the FindWindoEx is not seeing it as a button or if it's just not finding &Save As.

Do you have any suggestions on how to find out the properties of the window so I can find the &Save As so I can execute it.  Let me know.

Thx
ajpelkey
0
 
LVL 2

Expert Comment

by:wuttrain
ID: 9696962
Is the Save As button part of the window "CRDB PSR Viewer - [C:\CAPACITY FOLDER\TKS.PSR]"? or is it on a different window? It could be a child of a different window that's why it returns 0.

You can try Spy++, look for the Save As button and check if it is a child of the specified window.


0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:ajpelkey
ID: 9698307
wuttrain,

I think it might be a child window so my next question would be, how do I get it to read the button on a child window?  As I look at it, the tree shows as follows:

"CRDB PSR Viewer - [C:\CAPACITY FOLDER\TKS.PSR]" FNWND380
   "" MDIClient
      "C:\CAPACITY FOLDER\TKS.PSR" FNWND380

Any help would help.

Thx,
ajpelkey
0
 
LVL 5

Expert Comment

by:fantasy1001
ID: 9699140
I noticed that this will be a different issue if the Save As button is on a toolbar.
Because &Save As can be trigger with ALT+S,

Private Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

AppActivate "CRDB PSR Viewer - [C:\CAPACITY FOLDER\TKS.PSR]"
keybd_event 18, 0, 0, 0
keybd_event 83, 0, 0, 0
keybd_event 83, 0, &h2, 0
keybd_event 18, 0, &h2, 0

~ fantasy ~
0
 

Author Comment

by:ajpelkey
ID: 9701169
Thanks Fantasy1001,
 I have actualy gotten way past keyboard events now.  I am now down to just one keyboard issue and I am trying to figure out how to get rid of that one.

AJ
0
 
LVL 2

Expert Comment

by:wuttrain
ID: 9701840
is there a way you can access the Save As button using the Menu, because if you can, then don't bother accessing it through the toolbar. Access it the same way I access Save As submenu in Notepad.  let me know if it's possible

hwndWord = FindWindow(vbNullString, "test.txt - Notepad")
  hMainMenu = GetMenu(hwndWord)
  hMenu = GetSubMenu(hMainMenu, 0)  'get into the File Menu 0
  MenuID = GetMenuItemID(hMenu, 3) 'select on Save As submenu
  lRet = PostMessage(hwndWord, WM_COMMAND, MenuID, 0&) 'send the command to click Save As submenu
0
 

Author Comment

by:ajpelkey
ID: 9702250
wuttrain,

Nope.  It's a special viewer and the only thing in the one menu item is Open & Exit.

Also,  I am using your method in another program I use.  The problem I run into is that to logon, I have 2 "Edit" classes with Null names.  How do I define which one to put the User ID in and which one to put the password in.  Right now, it just finds the first Edit.

AJ
0
 
LVL 2

Expert Comment

by:wuttrain
ID: 9702930
for example, you will have this Enter Network Password dialog when trying to login to a website. i can find the handles of these edit boxes by using the function below.  hope that helps.

anyway, is there a way i can try using the viewer program you are using so I can test it also.

Function FindEdits()
Dim lHwnd1 As Long
Dim lHwnd2 As Long
Dim tempHwnd As Long

  tempHwnd = FindWindow(vbNullString, "Enter Network Password")
 
  lHwnd1 = FindWindowEx(tempHwnd, 0, "Edit", vbNullString)
  lHwnd2 = FindWindowEx(tempHwnd, lHwnd1, "Edit", vbNullString)

End Function
0
 

Author Comment

by:ajpelkey
ID: 9703209
wuttrain,

I can get you the viewer in itself, no problem.  By itself, it's useless.  You need a *.psr report and as far as I know, it's only available in the company I work for and it is proprietary.  I wish I could, it would make it SOOOO much easier.

The other solution worked perfect.

I am getting ready to award points but continue to post a question to see if you can help me with something else.

Here's the problem:

I run the code pretty much as you gave me and it works from start to finish on my XP machine.  The only problem is that when it finishes on my XP machine, I get the following error:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
x  dwwin.exe - Application Error  x
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The exception Breakpoint
A breakpoint has been reached.
(0x80000003) occurred in the application at location 0x77f75a58

Any idea why?

I run the same code on my NT machine and I get the following:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
x  dwwin.exe - Application Error  x
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The instruction at "0x11553381A" referenced memory at "0x02591bec" The memory could not be "Read".

Any idea why?

Thx
AJ
0
 
LVL 2

Expert Comment

by:wuttrain
ID: 9703332
I am using win98 when testing the codes I gave you and just tested it in XP, and it works fine.  Not tested it on NT though. And I'm not sure why it's happening.

have you posted this as a new question, I suggest that you do that so others can also work and help with you.
0
 

Author Comment

by:ajpelkey
ID: 9703609
wuttrain,
not yet, it was my next course of action.

Thx for your help.  It's been invaluable.

AJ
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now