How can I send keystrokes and mouse movement to a specific PID? - python

How can I send keystrokes and mouse movements to a specific running program through its PID. I've used both pywinauto and pynput, and they work great, but I want to send keys to a program that is not in focus. I found this question: How to I send keystroke to Linux process in Python by PID? but it never explains what filePath is a path to.
If you could help solve for this example, that would be great! I want to send the "d" key to an open Minecraft tab for 10 seconds, and then send the "a" key for the next 10 seconds and stop. I would need this to be able to run in the background, so it could not send the keys to the computer as a whole, but only to the Minecraft tab. I am on Windows 10 by the way.
Any help would be appreciated!

Pretty sure you won't be able to, at least not easily let me explain a little bit how all of this works.
Lets start with the hardware and os, the OS has certain functions to read the input you give the computer. This input goes into a "pipe", the OS is reading input, and putting into the pipe, on the other side of the pipe there may be an application running, or it may not. The OS typically manages this (which app to put on the pipe listening) by defining which app/window is active. Apps access this pipe with the API given by the OS, they read the input and decide on it.
The libraries you cited above, change the values of the keyboard and mouse, in other words, they make the OS read other values, not the real ones, then the OS puts them in the "pipe", and are read by the app that is listening on the pipe (the one active). Some apps have their own API's for this, but I would guess Minecraft doesn't. If they don't have an API, what can you do? well, as I said, nothing easy, first of all "hacking" the app, in other words change it to listen to some other input/output rather than the one given by the OS, (this would be you making your own API). The other one would be you changing the OS, which would also be extremely hard, but maybe a tiny bitty easier. It also depends on your OS, I think Microsoft does offer input injection api's
So, simple options, first, run a VM with a GUI and use pywinauto, pyautogui, etc. The other option would be if you can run it in the browser, do so, and use something like Selenium to automate the input.
Quick note, why does selenium works and the browser can read input in the background? Easy, it's not, it just executes the code it would execute if it would have read the input! javascript, cool isn't

With ahk you can do this with Python+AutoHotkey
pip install ahk
pip install "ahk[binary]"
from ahk import AHK
from ahk.window import Window
ahk = AHK()
win = Window.from_pid(ahk, pid='20366')
win.send('abc') # send keys directly to the window
Note that some programs may simply ignore inputs when they are not in focus. However, you can test this works in general even when not in focus by testing with a program like notepad
Full disclosure: I author the ahk library.

Related

Tracking focus changes

I'm trying to track the window focus changes (what application is in the foreground) with python 3.7 in a windows 10 (64b) machine because I'd like to log how much time I spend using each application (I hope chrome is a different app for each tab XD)
I tried to search in the web about how to do it but didn't find it (odd). For now I learnt that I have to install win32api (pypiwin32) and that with this code I can get the name of the window
from win32gui import GetWindowText, GetForegroundWindow
print(GetWindowText(GetForegroundWindow()))
That works fine but I don't want to make a loop with that every second, I'd like to have a callback that when the event 'onWindowFocusChange' or something like that is called run that.
EDIT: As David Heffeman pointed out, I was using wrong terminology. What I meant is the piece of software that I'm interacting with at each point. (None if the screen is blocked, If I'm playing a game and listening to music, the game, if I'm reading a web or a pdf that browser or reader, etc... hope this clarifies the matter.
This example code here logs all focus changes: https://gist.github.com/keturn/6695625

Real Time Python program

I have a project in my job.
The target is to prepare 14 SD cards for provisioning any Raspberry Pi 3.
So I have to found a solution to do it automatically and follow which SD card is ready to start and which one is complete.
I have the idea to build with a Python3 program and a tkinter interface because I know a little bit Python and not others languages...
The program should work like this :
List every Windows drives where SD card is mounted
Push a button in front of the letter of the SD card drive to start the provisioning.
The provisioning is all steps to make the SD cards bootable with an OS. So I have to pass some DISKPART commands or equivalent in Python I think, if you have any suggestions ?
Show a statut in front of each drive to follow if the drive is pending, working, complete, etc.
I have a huge interogation about this. My program has to refresh every informations. I mean the program should work in real time or not ? What is the best way to proceed ?
To be clear, I don't want someone building to me this program, I just want to have some good idea to implement.
Thank you
You can use this module to execute commands. For example:
import subprocess
completed = subprocess.run(['ls', '-1'])
print('returncode:', completed.returncode)
I can't help with the Python part, but if you have a WinAPI window with message handling (so the WindowProc thing), WM_DEVICECHANGE is the message, here are the actual event categories and RegisterDeviceNotification is how you subscribe to it. Complete (but C) MSDN example is here
While implementing it may require some work, viability itself depends on getting access/not getting access to the message queue (from Python). Based on this and this it seems to be possible, but I have no experience with it.

How do i pass on control on to different terminal tab using perl?

I am trying to automate a scenario in which, I have a terminal window open with multiple tabs open in it. I am able to migrate between the tabs, but my problem is how do i pass control to another terminal tab while i run my perl script in a different tab.
Example: I have a terminal open with Tab1,Tab2,Tab3,Tab4 open in the same terminal, i run the perl script in Tab3 and i would want to pass some commands onto Tab1. Could you please tell me how can i do this ??
I use GUI tool to switch between tabs X11::GUITest and use keyboard shortcuts to switch between tabs, any alternative suggestion is welcome, my ultimate aim is to pass control on to a different tab.
The main thing to understand is that each tab has a different instance of terminal running, more importantly a different instance of shell (just thought I would mention as it didnt seem like you were clear about that from your choice of words). So "passing control" in such a scenario could most probably entail inter-process communication (IPC).
Now that opens up a range of possibilities. You could, for example, have a python/perl script running in the target shell (tab) to listen on a unix socket for commands in the form of text, which the script can then execute. In Python, you have modules subprocess (call, Popen) and os (exec*) for this. If you have to transfer control back to the calling process, then I would suggest using subprocess as you would be able to send back return codes too.
Switching between tabs is a different action and has no consequences on the calling/called processes. And you have already mentioned how you intend on doing that.

Simplest way to have Python output, from a compiled package?

Prior info: I'm on a Mac.
Q: How can I get terminal-like text output from the program execution, if I compile it with py2app for redistribution?
My case is a program that copies a lot of big files and takes a while to process so I would like to at least have an output notification everytime each file is copied.
This is easy if I run it on the command line, I can just print a new line.
But when I make a self-sufficient package, it simply opens on the bottom dock, with no window, and closes upon completion.
A simple text window would be fine.
Thanks in advance.
If you want to create a simple text window, you need to pick a GUI framework to do that with. For something this simple, there's no reason not to use Tkinter (which comes with any Python) or PyObjC (which is pre-installed with Apple's Python 2.7), unless you happen to be more familiar with wx, gobject, Qt, etc.
At any rate, however you do it, you'll need to write a function that takes a message and appends it to the text window (maybe creating it lazily, if necessary), and call that function wherever you would normally print. You may also want to write and install a logging handler that does the same thing, so you can just log.info stuff. (You could instead create a file-like object that does this and redirect stdout and/or stderr, but unless you have no control over the printing code, that's going to be a lot more work.)
The only real problem here is that a GUI needs an event loop, and you probably just wrote your code as a sequential script.
One way around that is to turn your whole current script into a background thread. If you're using a GUI library that allows you to access the widgets from background threads, everything is easy; your printfunc just does textwidget.append(msg). If not, it may at least have a call_on_main_thread type function, so your printfunc does call_on_main_thread(textwidget.append, msg). If worst comes to worst (and I believe with Tkinter, it does), you have to create an explicit queue to push messages through, and write a queue handler in the event loop. This recipe should give you an idea. Replace the body of workerThread with your code, and end it with self.endApplication(). (There are probably better examples out there; this was just what I found first in a quick search.)
The other way around that is to have your code cooperatively operate with the event loop. Some libraries, like wx, have functions like SafeYield that make things work if you just call it after every chunk of processing. Others don't have that, but have a way to explicitly drive the event loop from your code. Others have neither—but every event loop framework has to have a way to schedule new events, so you can break your code up into a sequence of functions that each finish quickly and then do something like root.after_idle(nextfunc).
However… are you sure you need to do this?
First, any app, including one created by py2app, will send its stdout to the terminal if you run it with Foo.app/Contents/MacOS/Foo. And you can even set things up so that open Foo.app works that way, if you want. Obviously this doesn't help for people who just double-click the app in Finder (because then there is no terminal), but sometimes it's sufficient to just have to output available when people need it and know how to follow instructions.
And you can take this farther: Create a Foo.command file that just does something like $(dirname $0)/Foo.app/Contents/MacOS/Foo, and when you double-click that file, it launches Terminal.app and runs your script.
Or you can get even simpler: Just use logging to syslog the output, and if you want to see when each file is done, just watch the log messages go by in Console.app.
Finally, do you even need py2app in the first place? If you don't have any external dependencies, just rename you script to Foo.command, and double-clicking it will run it in Terminal.app. If you do have external dependencies, you might still be able to get away with bundling it all together as a folder with a .command in it instead of as a .app.
Obviously none of these ideas are exactly a professional or newbie-friendly way to build an interface, so if that matters, you will have to create a GUI.

pexpect output in different window

Now I am working in a project where the testscript has to connect many (3-10) remote computers (SSH and do some stuff).
I started to use the pexpect and it is simple as a button. It works fine.
I want to see the communication during test. I know it is possible to redirect the log to the screen. But in this case the logs (from different computer) are mixed.
What I would like is to open new terminal window (or consol or whatever) for every new spawn object. In this case I could see all communication in different windows. Additionally I would like to keep the possibility of spawn.interact() in every window.
I feel that it is possible somehow but I don't know how. I think some file pointer (or pipe) should pass to the new window somehow(?)
(SecureCRT knows sometihng like this, it has tabbed consol windows and can access them separately, but it is a commercial product)
Or let me make the problem more simple.
If I do this, I can open a new shell in a new window:
p=Popen(["cygstart", "bash"])
How can I read and write into this shell from my script (parent) to see it in this new window?
I would really appreciate it, if one of you could point me in the right direction.
It is enough if you tell me what to read or find for (on Google) because I did not find anybody such kind of problem.
The environment is cygwin.
Thanks in advance
br:drv
Have you tried using the logfile parameter?
child = pexpect.spawn('some_command')
mylog = open('/tmp/mylog','w')
child.logfile = mylog
This will automatically log all communication to the file, including commands you enter after calling spawn.interact()
More info available on the website: http://pexpect.sourceforge.net/pexpect.html
Search for 'logfile' to find the relevant documentation.

Categories