Sending keystrokes to Windows exe programs
eryksun ()
eryksun at gmail.com
Sat Apr 2 23:08:05 EDT 2011
On Saturday, April 2, 2011 12:48:44 PM UTC-4, Alex van der Spek wrote:
>
> I can start a windows program on Vista with:
>
> >>> import subprocess
> >>> dva=subprocess.Popen(DVAname,stdin=subprocess.PIPE)
>
> Unfortunately sending keystrokes with communicate() does not appear to work:
>
> >>> dva.communicate('F2')
Is this a GUI process? If so, it probably doesn't have stdin unless it also has a console (possibly hidden).
To send keys to a GUI Window, you can use win32com (from the pywin32 extensions) to execute WScript commands:
import time
import win32com
import win32com.client
shell = win32com.client.Dispatch('WScript.Shell')
shell.Run('notepad')
time.sleep(0.1)
shell.AppActivate('notepad')
shell.SendKeys("Hello World", 0)
shell.SendKeys("{Enter}", 0)
shell.SendKeys("{F5}", 0) # F5 prints the time/date
Documentation for SendKeys:
http://msdn.microsoft.com/en-us/library/8c6yea83
SendKeys only sends to the active Window. If you need to send keys to a background Window, you can use win32 messaging.
If you load the process with CreateProcess, you'll get the the main thread ID (tid) as well as the process ID (pid). Then you can enumerate handles for the thread's windows into a dictionary keyed by the window classes (or window class + window title).
Here's the example with notepad, but this time using win32 messaging:
import time
import win32con
import win32api
import win32gui
import win32process
_, cmd = win32api.FindExecutable('notepad')
_, _, pid, tid = win32process.CreateProcess(
None, # name
cmd, # command line
None, # process attributes
None, # thread attributes
0, # inheritance flag
0, # creation flag
None, # new environment
None, # current directory
win32process.STARTUPINFO ())
# wcallb is callback for EnumThreadWindows and
# EnumChildWindows. It populates the dict 'handle' with
# references by class name for each window and child
# window of the given thread ID.
def wcallb(hwnd, handle):
handle[win32gui.GetClassName(hwnd)] = hwnd
win32gui.EnumChildWindows(hwnd, wcallb, handle)
return True
handle = {}
while not handle: # loop until the window is loaded
time.sleep(0.1)
win32gui.EnumThreadWindows(tid, wcallb, handle)
# Sending normal characters is a WM_CHAR message.
# Function keys are sent as WM_KEYDOWN and WM_KEYUP
# messages using the virtual keys defined in win32con,
# such as VK_F5 for the f5 key.
#
# Notepad has a separate 'Edit' window to which you can
# write, but function keys are processed by the main
# window.
for c in "Hello World\n":
win32api.PostMessage(
handle['Edit'],
win32con.WM_CHAR,
ord(c),
0)
win32api.PostMessage(
handle['Notepad'],
win32con.WM_KEYDOWN,
win32con.VK_F5,
0)
win32api.PostMessage(
handle['Notepad'],
win32con.WM_KEYUP,
win32con.VK_F5,
0)
# SendMessage waits for a response, but PostMessage
# queues the message and returns immediately
More information about the Python-list
mailing list