I am trying to control a console application (JTAG app from Segger) from Python using the subprocess module. The application behaves correctly for stdout, but stdin doesn't seem to be read. If enable the shell, I can type into the input and control the application, but I need to do this programmatically. The same code works fine for issuing commands to something like cmd.exe.
I'm guessing that the keyboard is being read directly instead of stdin. Any ideas how I can send the application input?
from subprocess import Popen, PIPE, STDOUT
jtag = Popen('"C:/Program Files/SEGGER/JLinkARM_V402e/JLink.exe"', shell=True,
universal_newlines=True,
stdin=PIPE,
stdout=PIPE,
stderr=STDOUT)
jtag.stdin.write('usb\n')
jtag.stdin.flush()
print "Stdout:"
while True:
s = jtag.stdout.readline()
if not s:
break
print s,
jtag.terminate()
As shoosh says, I'd try to verify that the application really is looking for keyboard input. If it is, you can try Win32 message passing, or sending it keyboard input via automation.
For the message passing route, you could use the EnumWindows function via ctypes to find the window you're after, then using PostMessage to send it WM_KEYDOWN messages.
You can also send keyboard input via pywinauto, or the ActiveX control of AutoIt via win32com.
Using AutoIt:
from win32com.client import Dispatch
auto = Dispatch("AutoItX3.Control")
auto.WinActivate("The window's title", "")
auto.WinWaitActive("The window's title", "", 10)
auto.Send("The input")
I'm guessing that the keyboard is being read directly instead of stdin
This is a pretty strong assumption and before stitching a solution you should try to verify it somehow. There are different levels of doing this. Actually two I can think of right now:
- Waiting for keyboard events from the main windows loop. if this is the case then you can simulate a keyboard simply by sending the window the right kind of message. these can be wither
WM_KEYDOWN
or WM_CHAR
or perhaps some other related variants.
- Actually polling the hardware, for instance using
GetAsyncKeyState()
. This is somewhat unlikely and if this is really what's going on, I doubt you can do anything to simulate it programatically.
Another take on this is trying to use the on-screen keyboard and see if it works with the application. if it does, figure out how to simulate what it does.
Some tools which might be helpful -
- Spy++ (comes with Visual Studio) - allows you to see what messages go into a window
- strace allows you to see what syscalls a process is making.