SendKeys

Description

The existing SendKeys class does not have a managed way to activate an external application. MSDN recommends that you should use the FindWindow and SetForegroundWindow APIs. However, this alone does not ensure that the desired application will have keyboard focus while the keys are being sent. This replacement module sends keys directly to the specified window without error. I hope!

Before I get into any details of what's under the hood of the attached SendKeys modules, I want to explain how developers can get working with it right away. Download the SendKeys module—choose either the .NET or VB 6 version—at the bottom of this post and unzip it. Add it to your project by pressing the Ctrl+d key combination. Now, point and click on the module you've downloaded and unzipped.

Once you've added the module to your project, all you have to do is type in "SendKeys" to view available methods. The Intellisense window in VB2005-VB2008 will pop up with a detailed description of how to use a function or any one of its parameters.

Get a Handle on Things

In many cases, you can send or post a message directly to a window, without changing the foreground window at all. Create a new Notepad document on the desktop and then open it. It should be named "New Text Document - Notepad" for the following demo. To obtain the handles of the windows with focus, just use the WINFOCUS structure returned by the GetWinFocus or the GetWinHandles function. If true is specified in the showNames parameter of the GetWinFocus function, the text and class names of the ancestors will be shown in a messagebox. This helps you find the path of the windows, which can be used in GetWinHandles.

If you want to get the handles of the windows that currently have keyboard focus.

'Place focus on that window during the next 3 seconds
SendKeys.Sleep(3000)
Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinFocus(True, True)
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

If you want to get the handle of a child window that's on a main window, that is to receive keyboard focus. This will get the handle of the first editable window inside of a notepad, and the handle of the first notepad itself.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad", 1, "Edit", 1)
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

If you want to get the handle of the main window by its application title.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad")
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

If you want to get the handle of the main window by its class name.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("Notepad")
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

If you want to get the handle of the main window by its process name.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("notepad.exe")
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

If you want to get the handle of the main window of a new process with a valid file path.

Dim sSystem As String = ""
sSystem =  System.Environment.SystemDirectory.Substring _
(0, System.Environment.SystemDirectory.Length - 9)
Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles(sSystem & "\notepad.exe")
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

If you want to get the handle of window, by using special commands, enclose them in brackets. See the GetCommands sub for more info.

SendKeys.Sleep(3000)
Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("{foreground}")
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

Recommended

All you need to do now is insert the focus handle structure into the parameter of the Text function. This will erase any existing text and write "Hello!" to the window with the blinking caret—a Notepad.

SendKeys.Text("Hello!", w)

If you want to press a key only down or up, use the Message function.

SendKeys.Message(Keys.Space, w)

This will send the space key down, and up, to safely press a button, or a checkbox that is in focus. You may specify up or down if you want to send key combinations. If these methods do not work on an external window, it's usually because there is some dynamic operation being invoked by your input.

For example, pressing a button can cause some dynamic operation to be invoked before the key message is sent up. You can try setting the last parameter to True, so that the message is posted into the queue, instead of waiting for a return.

Secondary

In some cases, this is just not enough, and you may need to inject these keys, similar to the way that the SendKeys class does, by typing them in, on a virtual keyboard. For more information about the SendKeys class, visit MSDN.

If you want to inject text into a window.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad", 1, "Edit", 1)
SendKeys.Send("Hello", w)

If you want to send a key command, enclose it within brackets.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("Form1", 1, "GroupBox1", 1, "GroupBox2", _
   1, "GroupBox3", 1, "Start", 1)
SendKeys.Send("{space}", w)

If you want to call the send method in one line, insert the return value of the GetWinHandles function.

SendKeys.Send("Hello", SendKeys.GetWinHandles("New Text Document - _
   Notepad", 1, "Edit", 1))

If you want to send input to the current foreground window.

'Place focus on notepad during these 3 seconds
SendKeys.Sleep(3000)
SendKeys.Send("Hello", Nothing)

If you want to send keys as an event, and then return the foreground window to it's previous position before the call, specify false in the asMessage parameter, and true in the rForeground parameter.

'Place focus on a second notepad during these 3 seconds
SendKeys.Sleep(3000)
Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad", 1, "Edit", 1)
SendKeys.Send("Hello", w, False, True)

SendKeys

If you want set focus without sending keys.

SendKeys.Send("", SendKeys.GetWinHandles("New Text Document - _
   Notepad", 1, "Edit", 1), False) 

If you want to get the number of keys sent.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad", 1, "Edit", 1)
Dim sent As Int32 = SendKeys.Send("Hello", w)
MessageBox.Show(sent.ToString & " keys sent")

If you want to view available commands.

SendKeys.GetCommands()

If you want to open a file menu. (Alt + f)

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad")
SendKeys.Send("%(f)", w, False)

If you want to access sub menu shortcuts. (Alt + fx)

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad")
SendKeys.Send("%(fx)", w, False)

If you want capitalize a letter. (Shift + a)

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad")
SendKeys.Send("+(a)", w, False)

If you want print the current document. (Ctrl + p)

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad")
SendKeys.Send("^(p)", w, False)

If you want to open the system menu of a notepad and Maximize screen. (Alt + Space)

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("New Text Document - Notepad")
SendKeys.Send("%({space}x)", w, False)

If you want to open start menu. (Ctrl + Escape)

SendKeys.Send("^({escape})", Nothing, False)

If you want to open Task manager. (Ctrl+Shift+Escape)

SendKeys.Send("^(+({escape}))", Nothing, False)

If you want to log off of 2000/XP immediately. (Win + L)

SendKeys.Send("#(l)", Nothing, False)
Important Note: Different versions of VB.NET have different names for certain keys. For example, the {enter} key on VB.NET 2003 is now the {return} key on VB.NET 2005. I recommend checking what the key names are for your version of VB.NET, by using the GetCommands sub.

Here is a complete list of key commands for 2005 with the 2.0 framework:

KeyCode Command KeyCode Command KeyCode Command
0 None 85 U 171 BrowserFavorites
1 LButton 86 V 172 BrowserHome
2 RButton 87 W 173 VolumeMute
3 Cancel 88 X 174 VolumeDown
4 MButton 89 Y 175 VolumeUp
5 XButton1 90 Z 176 MediaNextTrack
6 XButton2 91 LWin 177 MediaPreviousTrack
7 LButton, XButton2 92 RWin 178 MediaStop
8 Back 93 Apps 179 MediaPlayPause
9 Tab 94 RButton, RWin 180 LaunchMail
10 LineFeed 95 Sleep 181 SelectMedia
11 LButton, LineFeed 96 NumPad0 182 LaunchApplication1
12 Clear 97 NumPad1 183 LaunchApplication2
13 Return 98 NumPad2 184 Back, MediaNextTrack
14 RButton, Clear 99 NumPad3 185 Back, MediaPreviousTrack
15 RButton, Return 100 NumPad4 186 Oem1
16 ShiftKey 101 NumPad5 187 Oemplus
17 ControlKey 102 NumPad6 188 Oemcomma
18 Menu 103 NumPad7 189 OemMinus
19 Pause 104 NumPad8 190 OemPeriod
20 Capital 105 NumPad9 191 OemQuestion
21 KanaMode 106 Multiply 192 Oemtilde
22 RButton, Capital 107 Add 193 LButton, Oemtilde
23 JunjaMode 108 Separator 194 RButton, Oemtilde
24 FinalMode 109 Subtract 195 Cancel, Oemtilde
25 HanjaMode 110 Decimal 196 MButton, Oemtilde
26 RButton, FinalMode 111 Divide 197 XButton1, Oemtilde
27 Escape 112 F1 198 XButton2, Oemtilde
28 IMEConvert 113 F2 199 LButton, XButton2, Oemtilde
29 IMENonconvert 114 F3 200 Back, Oemtilde
30 IMEAceept 115 F4 201 Tab, Oemtilde
31 IMEModeChange 116 F5 202 LineFeed, Oemtilde
32 Space 117 F6 203 LButton, LineFeed, Oemtilde
33 PageUp 118 F7 204 Clear, Oemtilde
34 Next 119 F8 205 Return, Oemtilde
35 End 120 F9 206 RButton, Clear, Oemtilde
36 Home 121 F10 207 RButton, Return, Oemtilde
37 Left 122 F11 208 ShiftKey, Oemtilde
38 Up 123 F12 209 ControlKey, Oemtilde
39 Right 124 F13 210 Menu, Oemtilde
40 Down 125 F14 211 Pause, Oemtilde
41 Select 126 F15 212 Capital, Oemtilde
42 Print 127 F16 213 KanaMode, Oemtilde
43 Execute 128 F17 214 RButton, Capital, Oemtilde
44 PrintScreen 129 F18 215 JunjaMode, Oemtilde
45 Insert 130 F19 216 FinalMode, Oemtilde
46 Delete 131 F20 217 HanjaMode, Oemtilde
47 Help 132 F21 218 RButton, FinalMode, Oemtilde
48 D0 133 F22 219 OemOpenBrackets
49 D1 134 F23 220 Oem5
50 D2 135 F24 221 Oem6
51 D3 136 Back, F17 222 Oem7
52 D4 137 Back, F18 223 Oem8
53 D5 138 Back, F19 224 Space, Oemtilde
54 D6 139 Back, F20 225 PageUp, Oemtilde
55 D7 140 Back, F21 226 OemBackslash
56 D8 141 Back, F22 227 LButton, OemBackslash
57 D9 142 Back, F23 228 Home, Oemtilde
58 RButton, D8 143 Back, F24 229 ProcessKey
59 RButton, D9 144 NumLock 230 MButton, OemBackslash
60 MButton, D8 145 Scroll 231 Packet
61 MButton, D9 146 RButton, NumLock 232 Down, Oemtilde
62 XButton2, D8 147 RButton, Scroll 233 Select, Oemtilde
63 XButton2, D9 148 MButton, NumLock 234 Back, OemBackslash
64 64 149 MButton, Scroll 235 Tab, OemBackslash
65 A 150 XButton2, NumLock 236 PrintScreen, Oemtilde
66 B 151 XButton2, Scroll 237 Back, ProcessKey
67 C 152 Back, NumLock 238 Clear, OemBackslash
68 D 153 Back, Scroll 239 Back, Packet
69 E 154 LineFeed, NumLock 240 D0, Oemtilde
70 F 155 LineFeed, Scroll 241 D1, Oemtilde
71 G 156 Clear, NumLock 242 ShiftKey, OemBackslash
72 H 157 Clear, Scroll 243 ControlKey, OemBackslash
73 I 158 RButton, Clear, NumLock 244 D4, Oemtilde
74 J 159 RButton, Clear, Scroll 245 ShiftKey, ProcessKey
75 K 160 LShiftKey 246 Attn
76 L 161 RShiftKey 247 Crsel
77 M 162 LControlKey 248 Exsel
78 N 163 RControlKey 249 EraseEof
79 O 164 LMenu 250 Play
80 P 165 RMenu 251 Zoom
81 Q 166 BrowserBack 252 NoName
82 R 167 BrowserForward 253 Pa1
83 S 168 BrowserRefresh 254 OemClear
84 T 169 BrowserStop 255 LButton, OemClear
    170 BrowserSearch    

SendKeys

Mouse Functions

If you want to get the windows that have mouse focus. The main window and child under the cursor.

SendKeys.Sleep(3000)
Dim w As SendKeys.WINFOCUS = SendKeys.GetWinFocus(True, False)
MessageBox.Show(w.Foreground.ToString & vbCrLf & w.Focus.ToString)

If you want to click a button or other window.

Dim w As New SendKeys.WINFOCUS
w = SendKeys.GetWinHandles("Form1", 1, "GroupBox1", 1, "GroupBox2", _
   1, "GroupBox3", 1, "Start", 1)
SendKeys.Click(Buttons.LeftClick, w)

If you want to move from current cursor position.

SendKeys.Click(Buttons.Move, Nothing, False, False, True, 100, 100)

If you want to move the cursor to screen coordinates.

SendKeys.Click(Buttons.MoveAbsolute, Nothing, False, False, True, _
   100, 100)

If you want to click the 12th menu item, as a command message.

SendKeys.ClickMenu(True, "Form1", 1, "File", 1, "Item2", 1, "Item6", _
   1, "Item9", 1, "Item10", 1, "Item12", 1)

If you want to click the 23rd menu item.

SendKeys.ClickMenu(True, "Form1", 1, "Edit", 1, "Item15", 1, _
   "Item21", 1, "Item23", 1)

If you want to click the 12th menu item, by specifying the indexes only and no name.

SendKeys.ClickMenu(True, "Form1", 1, "", 1, "", 1, "", 3, "", 2, _
   "", 1, "", 2)

If you want to click an item by specifying both captions and indexes.

SendKeys.ClickMenu(True, "Form1", 1, "Edit", 1, "Item15", 1, _
   "Item18", 2)

If you want to wait for a window to exist before moving on, use the WaitForWindow function.

SendKeys.WaitForWindow("Print")

What's Under the Hood?

This module is built upon previous classes, such as InputToWin and SendKeysToWindow, which were pretty reliable compared to SendKeys.Send but were still incomplete. The most reliable methods for sending keys are Text and Message. Another dependable method is the new Send method; it sends messages or uses a keyboard hook to ensure that the foreground window is maintained, and only the keys sent from inside the module are allowed. It also can use the AttachThreadInput API when the intended focus window is an external application. You now can send keys directly to a child window by using the GetWinHandles or GetWinFocus(False) methods, with the WINFOCUS structure. The SendKeys module is fully commented line by line, to make it easier for others to learn and understand what's going on behind the scenes.

Advantages of the SendKeys Module over the SendKeys Class

Keyboard focus is maintained on the application by using a keyboard hook and SetForegroundWindow. When keys are sent from this module, external keys entered by the user are ignored by the hook. Other applications are locked out from using the SetForegroundWindow function while keys are being sent. The foregroundwindow can be returned to its original position. When a key being pressed represents an action that starts a new window, you can wait until that window exists before sending more keys. Win+key combos are now possible (2000/Xp) and are expressed as a string: "#(l)" (Win+L). All keys between 0 and 255 can be called! See the GetCommands sub for all available commands. GetWinHandles can find and verify any window handle, or start an executable path. See the GetCommands sub. The Sleep method provides a unique way to overcome timing issues. Complex key combinations are possible. Keys can be sent to a disabled, minimized, or hidden window. Strings can be repeated; in other words, "{hello 10}" repeats the hello string ten times.

Disadvantages of the SendKeys Module Compared to the SendKeys Class

None yet known. Let me know if you find any!

Author name: Shane Findley



About the Author

Shane Findley

Developer of applications for use in number theory.

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • With the average hard drive now averaging one terabyte in size, the fallout from the explosion of user-created data has become an overwhelming volume of potential evidence that law-enforcement and corporate investigators spend countless hours examining. Join Us and SANS' Rob Lee for our 45-minute webinar, A Triage and Collection Strategy for Time-Sensitive Investigations, will demonstrate how to: Identify the folders and files that often contain key insights Reduce the time spent sifting through content by …

Most Popular Programming Stories

More for Developers

RSS Feeds