Python : get master volume windows 7 - python

I am trying to built an App in which user has to just scroll his/her mouse over the windows sound icon to change the sound level. Linux users are already familiar with this.
I have divided my problem in these steps:
1.) Get current audio device list using a python api.
2.) Control the master voulme using the api.
3.) Attach a mouse event listener to it.(Sorry i am from Java background).
4.) Get mouse event listener method to do my work .
Plz suggest a proper python API to achieve my task.
And is this the correct approach towards my problem statement or there is a better way to approach this.

For this purpose you could use PyWin32 http://sourceforge.net/projects/pywin32/ or ctypes.
And your approach is pretty fine.
Here's a simple example for mouse with pywin32:
import win32api
import win32con
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
click(10,10)
and here's a similar one with ctypes:
import ctypes
ctypes.windll.user32.SetCursorPos(10, 10)
ctypes.windll.user32.mouse_event(2, 0, 0, 0,0)
ctypes.windll.user32.mouse_event(4, 0, 0, 0,0)
Ctypes is somewhat harder sometimes to figure out and debug (requieres ALOT of time on MSDN), but it's awesomely fast.

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 get user application (not processes) information in Windows using Python

I'm trying to obtain the information about the applications launched by the user in a Windows device. My idea is to obtain the same information that the Task Manager shows abount Apps, like RAM, CPU and Disk usage.
However, I can only find libraries that provide information about all the running processes, such as tasklist, wmi or psutil, and not only about the applications launched by the user. I also tried any way to differentiate background proceses from user applications, but I found nothing.
Is there any way to obtain the information above mentioned only about user applications?
Thanks.
I am not an expert in these things, but perhaps you would be interested in win32com, win32gui, or win32api and perhaps others. As I know these are very low level modules that allow you to interact with stuff like that. Here is a short script I made to force a certain window to remain on top of my screen even if I click on another window:
import win32gui
import win32con
hwnd = win32gui.FindWindow(None, 'Snipping Tool')
print(hwnd)
win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 200, 200, 425, 325, 0)

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

How get input device path with Xlib in Xorg?

There is some way to get the device path of a mouse and keyboard using Xlib based in a looping with XNextEvent? I need to know what /dev/input/event* generates a event specific like mouse press and keyboard key F1 press.
I'm using evdev for input devices in Xorg, I searched documentation and cannot find a way.
I accept too suggestion of some app that I can use to identify input device based in events like mouse press and keyboard press.
Thanks.
Edit: If there is a way to make this using another lib, preferable one with bindings for python, please let me know.
I realize that Xlib do not have a method to get the file descriptor of the input devices, so I figured out another way to resolve this case, is not ready yet, but apparently is the best way to follow, just posting here for someone with the same problem.
I'm using the module python-evdev (installed with pip in ubuntu), with this module I can monitor the devices is /dev/input/event*, so I just need to start a thread for each device that I previous identified which is a mouse or keyboard (using the module evdev and checking if device have "capabilities(verbose=True)" with event codes like ecodes.KEY_F1 and ecodes.BTN_MOUSE), and when a event occur, write to a shared variable, that I should monitor.
For the graphic interface running in Xorg, without Windows Managers, I using python-glade2, works like a charm, I run a Xorg with python-glade2 app using xinit.

Simulating Key Press event using Python for Linux

I am writing a script to automate running a particular model. When the model fails, it waits for a user input (Enter key). I can detect when the model has failed, but I am not able to use python (on linux) to simulate a key press event. Windows has the SendKeys library to do this but I was wondering if there is a similar library for python on linux.
Thanks!
Have a look at this https://github.com/SavinaRoja/PyUserInput
its cross-platform control for mouse and keyboard in python
Keyboard control works on X11(linux) and Windows systems. But no mac support(when i wrote this answer).
from pykeyboard import PyKeyboard
k = PyKeyboard()
# To Create an Alt+Tab combo
k.press_key(k.alt_key)
k.tap_key(k.tab_key)
k.release_key(k.alt_key)
A more low-level approach would be to create an uinput device from which you would then inject input events into the linux input subsystem. Consider the following libraries:
python-uinput
evdev
Example of sending <enter> with the latter:
from evdev import uinput, ecodes as e
with uinput.UInput() as ui:
ui.write(e.EV_KEY, e.KEY_ENTER, 1)
ui.write(e.EV_KEY, e.KEY_ENTER, 0)
ui.syn()
If the "model" is running graphically (with the X window system), the already-suggested xsendkey is a possibility, or xsendkeycode. If it's running textually (in a terminal window), then pexpect.
I recommend PyAutoGui. It's ridiculously simple to use, it's cross-platform and it's for Python 3 and 2.
In the linked page are listed the dependences and some code examples.
http://people.csail.mit.edu/adonovan/hacks/xsendkey.html
As many of the solutions I have found in this and in another well ranked SO response were either deprecated (PyUserInput) or using evdev, which failed (UInputError: "/dev/uinput" cannot be opened for writing) the simplest solution for me using Linux was pynput. One example directly from their docs:
from pynput.keyboard import Key, Controller
keyboard = Controller()
# Press and release space
keyboard.press(Key.space)
keyboard.release(Key.space)
# Type a lower case A; this will work even if no key on the
# physical keyboard is labelled 'A'
keyboard.press('a')
keyboard.release('a')
# Type two upper case As
keyboard.press('A')
keyboard.release('A')
with keyboard.pressed(Key.shift):
keyboard.press('a')
keyboard.release('a')
# Type 'Hello World' using the shortcut type method
keyboard.type('Hello World')
It worked like a charm!

Categories