How to send simulated keyboard strokes to the active window using SendKeys - python

I am new to Python and am trying to send a combination of key strokes to an application I open under Windows 7. While my script will work flawlessly when I invoke Notepad.exe for testing purposes, it does not with the actual application I am trying to use.
Here is my code so far:
import win32com.client
import time
import SendKeys
import os
from ctypes import *
shell = win32com.client.Dispatch("WScript.Shell")
os.startfile("C:\...exe")
time.sleep( 5 )
shell.SendKeys('%{F4}') # 'Alt+F4' to close the application again.
For some reason, the application does not close in reaction to the script. When I hit 'Alt + F4' on my keyboard, it closes as expected. Any ideas on what might be going on here?
Any help is welcome! Please bear in mind that I am new to Python ;-)
PS: I have already verified that the application runs in the active window by including this code snippet:
import win32ui
wnd = win32ui.GetForegroundWindow()
print wnd.GetWindowText()

OK ... I rebooted the system and for some reason it is working now. I am wondering if some process instance from previous programme invocations might have been lingering on the system. Anyway, I am now able to perform the manipulations as expected, even if I don't really understand what went wrong in the first place.
Thanks to everyone who took the time to repsond.

I know this was asked 6 years ago, but someone might be with the same problem, so here is a possible solution:
shell.AppActivate('Put_The_Name_Here')
The code above will select the program, file, etc that is opened but not activated, that, maybe, is your problem.
Hope this helps someone!

Related

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

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.

How to simulate the run button with a command line in Pycharm

I'm working on a script using the PyAutoGUI module. Sometimes the script gets stuck in a while loop because it's looking for pictures/images that are not shown due to connection problems etc. If this happens I want the program to start again from zero, so I want to simulate the play/run-button in Pycharm with a command line. Is this possible?
What it sounds like you want to do is restart your program if it doesnt respond. A similiar question appears to have been posted here: Python help - Need the ability to restart the script when it hangs or automatically set a timer so I would reccommend having a look at that. Simulating the run button in Pycharm might seem like a good idea at first but it is very specific and a bad practice to simulate user actions like that unless there is absolutely no viable alternative.
Thanks to Patel I managed to solve my issue. You can use ctrl+f5 to restart a script so now when I'm stuck in a while loop I'm using this code:
#Click toolbar Pycharm
pyautogui.moveTo(1672,15,1)
pyautogui.click()
#Rerun the script
pyautogui.hotkey("ctrl","f5")

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

"sh: Error: Can't open display" when I try to start a program from python

I have this really strange problem, basically I want to start xpdf (or Libreoffice) from my Python script, that is started by a systemd-service. When I start the script from terminal everything is working fine, but when I plug in my USB device that start the Service, I'll get this Error in my syslog:
sh[2321]: Error: Can't open Display
This error has something to do with X11, that's what my Google searches tell me.
So, my question is: How can I properly run a program like xpdf or libreoffice from Python?
import subprocess
subprocess.call("/usr/bin/xpdf")
This is it, basically. I know that it has something to do with the graphical enviroment, but I don't know how I can solve it.
The X display system has very good security to stop random local processes from just displaying stuff to the local screen (It was more a problem in the old days of expensive Sun and SGI systems where computer labs would often let users telnet to other boxes. Much fun could be had!).
If the user running the xpdf is the same user as the one who's logged into the X session, then you simply need to tell xpdf where to connect it's UI to. This is usually done by exporting DISPLAY=:0 to the environment, which means "connect to the first local screen". Most X programs also support -display :0 argument.
So do:
/usr/bin/xpdf -display :0
or:
DISPLAY=:0 /usr/bin/xpdf
It's very unlikely that you have more than one X session so :0 will work 99% of the time.
Since the issue is that xpdf isn't finding a display to connect to, we have two basic options: find and authenticate with an existing display, or make a new one. The latter is usually easier, something like:
xinit /usr/bin/xpdf -fullscreen $PDFFILE -- :2
This would start a new X display :2 running only xpdf, not even a window manager.
It finally worked, after trying and going crazy for around 2 weeks.
What worked was
os.system("DISPLAY=:0 /usr/bin/xpdf)
I know that subprocess.call is the better way to call the program, but it doesn't seem to work right now.
I'll try the way that Yann suggested later on, but for now I'm just overwhelmed with joy that it just works.
Thank you all for your help, I really appreciate it!

Python help - Need the ability to restart the script when it hangs or automatically set a timer

I currently have a python script that does exactly what I need it to do, however every now and then the script will hang and the only way to restart it is by killing the script and relaunching it.
I was wondering if there was a way to put in a few commands that will restart it lets say everytime it hangs or when a specific message appears or even just restart it on a timer eg:every 50 seconds.
I cannot provide the code through here, but I can provide it if we talk in private.
I am willing to pay you a bit of money if your fix does work.
please email me at stackoverflow1#shaw.ca
Thanks!
Edit: I see, ok - then is it possible to provide me with some codes which it will restart on a specific timer?
Edit2: Ok thanks everyone for their comments - I will get in touch with the person who built it to see if they can rewrite it from scratch to include a timer.
Cheers.
Feel free to pay me if you want, although it is by no means necessary.
Here:
import time
import threading
import os
def restart():
time.sleep(50)
os.execv('/full/path/to/this/script', ['second argument', 'third argument'])
def main():
t = threading.Thread(target=restart, args=(), name='reset')
t.start()
# ... The rest of your code.
If you have any buffers open that you care about (such as stdout) you'll want to flush them right before the call to execv up there.
I haven't tested this code, because I don't have a python interpreter handy at the moment, but I'd be surprised if it didn't work. That call to execv replaces the current context, so you don't get an increasingly deep hierarchy of child processes. All I'm doing, in case you're curious and want to know what magic phrase to google, is setting a "timer interrupt handler". For the pedants, no, I recognize this thing isn't directly handling any interrupts.
The numeric argument to sleep is in seconds. I would simply request that you not use my code in malware, unless it is for research purposes. I'm particular that way.
edit: Additionally, a lot of it was taken from here.

Categories