I am making application that controls a browser with SendKeys. But as SendKeys get the full control over the keyboard, I want to run this app under the different user. This way I will be working, the application will do what it have to do, and we will not make problems for each other).
The simplest code is
import time
import SendKeys
time.sleep(10)
SendKeys.SendKeys('hello')
I run it, focus on the field where I want to insert my text "hello", and wait. If I don't change the user, all is done as expected.
But when I run it, change the user and return after 10 seconds, I see that SendKeys sent nothing to the program.
How to send keystrokes to the program under the different user?
(I was trying to do the same with pywinauto, but the result was almost the same - all is good if I don't change the user, and error if I change it. So I thought that it is much simplier to resolve this problem with only SendKeys).
Just to summarize our discussion in comments and in the chat. Your wishes are very wide. I'm just trying to show you some directions to learn.
If you want to use SendKeys/TypeKeys/ClickInput methods (working as a real user), you need to run your automation script in the remote session, not locally. This is explained in details in my other answer: SetCursorPos fail with "the parameter is incorrect" after rdp session terminated.
If you want to run the automation on the same machine silently (in minimized state), there is an example for dealing with hidden windows: Python - Control window with pywinauto while the window is minimized or hidden. Just minimize the window and use silent methods (almost all except ClickInput and TypeKeys).
Feel free to ask more detailed questions about pywinauto and GUI automation.
Related
As the title explain, i'm trying to use the terminal to send commands as keystrokes to a GUI application that's minimized.
There is a lot of similar questions here on Stack with some great answers, but i'm having, mainly, three problems with the solutions i saw: Most of the solutions need the automated application to be the active one. Or, i can't normally use my keyboard while the script/process is running. Or worse, the solution works only on Windows OS.
I need what this person asked 2 months ago: Send keystrokes to a specific window (in background), but do something else in the meantime
But i want it on Linux.
I'm using Kubuntu 18.10, if that helps.
xdotool was close, but i couldn't quite get it to send the commands to a specific window or PID. It also uses "my keyboard", so i can't, for example, write an essay/code/browse online while xdotool is running. Pexpect also have this last problem.
AutoHotKey looks like it would work, but it's only for Windows and i'm trying to not use Wine. Same with pywin32.
keyboard (https://github.com/boppreh/keyboard) seems nice, but it can't send a command to a specific application. Same with PyAutoGUI.
I selected the Python tag because most of the solutions i saw use Python, but i'm open to any language.
Use a nested X server to input keystrokes without changing focus or keyboard grab.
Proof of concept:
Xephyr -resizeable :13
export DISPLAY=:13
xterm
xdotool type rhabarber
The Xephyr nested X server is started and will listen on local X socket 13 (whereas :0 typically identifies the currently running X server, but when multiple sessions are ran concurrently, it could be higher).
Then we set DISPLAY environment variable to :13, so any X application we start will connect to Xephyr; xterm is our target application here. Using xdotool or any other tool we can send keystrokes.
As the target X server is identified through $DISPLAY, applications can be started or input events triggered from elsewhere as well. If needed, you might also run a lightweight window manager within Xephyr, e.g. to 'maximize' the application so that it fills the whole Xephyr window.
I am very much concerned about my productivity all the time. I have recently come across this beautiful chrome extension Limitless
But this is only measuring what i'm doing within the chrome application. As I work most of the time with pdfs, videos etc, I want to develop similar application for linux(ubuntu) desktop enviroment.
Basically I want the script to run continuously as long as the workstation is on.
It should be able to know what I'm currently looking at (for eg a pdf file or a lecture video in vlc) and get the name of the respective file, start time, end times etc and finally post to db.
It is better if it could know if the system is idle or at sleep.
I don't have slightest clue at bash scripting. so my questions is could this task be accomplished with python.
What I've tried?
I started with a search in google "get current application python", "current window title python" etc etc and really surprised to see absurd results.
Please give me pointers on this.
I think you are asking for vocabulary. So I give you what I know.
You are using Ubuntu so your Window Manager may be Gnome.
The window manager knows which window has the focus.
So maybe you want to find out which window has the focus and you want to map it to the Process that opened the window.
What you need to focus on is is module for Python or a Python Binding for the window manager. This module is likely to also be able to control the windows.
The window manager is started with startx.
You could try to call a command line tool and catch the results
How do get the process list on command line:
https://stackoverflow.com/questions/53489/how-do-you-list-all-processes-on-the-command-line-in-windows
And how to call a tool with python:
Python subprocess.call and subprocess.Popen stdout
[edit] Repeating the call in Intervals and counting the intervals a process were running gives you a good estimation of running time of a process...
[edit2] As GreenAsJade said, you search a way to find out which windows has the focus.
See How do I detect the currently focused application?
I'm automating some common GUI tasks I have to do in an application, and I'm using a Python program and SendKeys to do it. So far I've had to activate the application I'm sending keys to (since SendKeys just sends the keystrokes to the active window), but I'd like to be able to send keystrokes to an application in the background. Is there a way to do that, or am I dreaming an impossible dream?
Thanks for your help.
pywinauto is another MS-only GUI automation tool, this one written in Python.
SendKeys is a Python module for Windows that can send one or more keystrokes or keystroke combinations to the active window.
If you need to do some automated work in the background, make another user/session and do it in that.
However if you must do something of this like on windows, I always reach for autoit.
It's M$ only and perfectly suited to automating tasks on that OS.
This is a frequent question in the autohotkey.com forums. Search under
"sending commands to controls". Basically, if you have the control ID, then it doesn't need to be visible in order to operate on it. There're more details on the forums.
good luck!
I have created a service which display a sort of splash screen on the desktop of a specific user and only when that user is logged in (kiosk user).
That splash screen, once entered a valid code, will tell that to the service and the service goes to sleep for an x amount of time (depending of the code).
The splash screen simply quits. Now when the service wakes up it sees that the splash is no longer there and so start it up.
This all is working, the only problem is that the launched application does not have focus, i.e. if I am working in notepad and the time is up, the splash screen is displayed (full screen though) behind notepad.
I only have to worry about Windows Vista, I am coding in Python using win32 extensions but I believe this problem lies in CreateProcessAsUser when called from the LocalSystem account.
Update:
The 'problem' is actually an on purpose limitation to prevent 'irritating' applications like mine from stealing focus.
You can change the behaviour by setting:
win32gui.SystemParametersInfo(win32con.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0)
which is equivalent in temporarily setting the registry value:
HKEY_CURRENT_USER\Control Panel\Desktop\ForegroundLockTimeout
This must be done as the user itself, so either build it in the app you are launching or build an launching helper for the app you want to launch.
However an application might want to prevent getting it's focus stolen by using some API call which I don't remember right now.
A probably good solution would be to find all window handles currently from that user and then use each of these handles to use win32gui.ShowWindow(handle, command) to minimize it.
Although for this particular problem setting the locktimeout setting was enough.
If anyone wonders how I managed to launch an application to a desktop from a service, here is a link to the code.
Have you tried launching another processes than your own from the service to see if it gets focus? Like notepad and see if it steals focus from your browser? If so perhaps its the program that can take back the focus when it starts.
I otherwise beilive it's the wShowWindow attribute from the STARTUPINFO struct the lpStartupInfo points to that should control it. You also need STARTF_USESHOWWINDOW in dwFlags to use nShowWindow. The values should be SW_SHOW i think, they are listed for the ShowWindow function if you want to try other.
For various very legitimated reasons, Microsoft would rather not see a service launching an app and stealing focus, however I found the following work around to still accomplish what I want.
The original intend is to have a kiosk like application hindered by a pass code like splash screen, which upon entering a 8 character code closes the splash screen for a period time as in the pass code defined. Originally the actual application to use was started by the autostart folder.
However I now rewrote it that it is launched from my service, this way I can hide the application by launching an helper application from the service that just hides the program and launches the splash screen, upon exiting the splash screen the program is returned to the previous state.
How can I detect, or be notified, when windows is logging out in python?
Edit:
Martin v. Löwis' answer is good, and works for a full logout but it does not work for a 'fast user switching' event like pressing win+L which is what I really need it for.
Edit: im not using a gui this is running as a service
You can detect fast user switching events using the Terminal Services API, which you can access from Python using the win32ts module from pywin32. In a GUI application, call WTSRegisterSessionNotification to receive notification messages, WTSUnRegisterSessionNotification to stop receiving notifications, and handle the WM_WTSSESSION_CHANGE message in your window procedure.
If you're writing a Windows service in Python, use the RegisterServiceCtrlHandlerEx function to detect fast user switching events. This is available in the pywin32 library as the RegisterServiceCtrlHandler function in the servicemanager module. In your handler function, look for the SERVICE_CONTROL_SESSIONCHANGE notification. See also the WM_WTSSESSION_CHANGE documentation for details of the specific notification codes.
There's some more detail in this thread from the python-win32 mailing list, which may be useful.
I hope this helps!
In a console application, you can use win32api.SetConsoleCtrlHandler and look for CTRL_LOGOFF_EVENT. In a GUI application, you need a window open and wait for the WM_QUERYENDSESSION message. How precisely that works (and if it works at all) depends on your GUI library.