Why is pyAutoGui not clicking in certain windows - python

I'm trying to make a python program to Automate the setup of a new computer. I used pyAutoGui to click on the Install button when prompted but it wont click on the button. It detects the image "Install.png" because it breaks the while loop when Adobe prompts to install. I tested it in paint and if I change the Install.png image to something on paint I can visually see it clicks. I tried the mouse library, moving it to the coordinates and then clicking, double- tripleClick, MouseDown -> sleep -> MouseUp, just MouseDown -> MouseUp, sending enter with pyAutogui, sending enter with shell, using subprocess and some other stuff. Nothing seems to work on the popup window Adobe gives. I printed the coordinates and they come out fine (I used DisplayMouseInfo to see of the coordinates were correct) I even hard coded the coordinates but it doesnt click install. Any answers would be appreciated, here is how it looks.
import os
import shutil
import subprocess
import psutil
import pyautogui as pg
import time
global path
path = os.getcwd()
def adobe_install():
adobe_setup_path = os.path.join(path, "Adobe.exe")
adobe_cmd = str("start " + adobe_setup_path)
os.system(adobe_cmd)
while pg.locateCenterOnScreen('Install.png', confidence=0.9) == None:
wait
time.sleep(2)
clk= pg.locateCenterOnScreen('Install.png', confidence=0.9)
pg.click(clk.x, clk.y)
EDIT
I tried the following
Install is just the a screenshot of the install button and the coordinates it prints (clk.x ; clk.y) are correct
import os
import shutil
import subprocess
import pyautogui as pg
import time
import pathlib
import winreg
import win32con
import win32gui
def adobe_install():
adobe_setup_path = os.path.join(path, "Adobe.exe")
adobe_cmd = str("start " + adobe_setup_path)
os.system(adobe_cmd)
while pg.locateCenterOnScreen('Install.png', confidence=0.9) == None:
wait
results = []
top_windows = []
win32gui.EnumWindows(windowEnumerationHandler, top_windows)
for i in top_windows:
if "Adobe Acrobat Reader DC (Continuous) - Setup" in i[1]:
print(i)
win32gui.ShowWindow(i[0],5)
win32gui.SetForegroundWindow(i[0])
bring_to_front(i[0])
break
time.sleep(2)
clk= pg.locateCenterOnScreen('Install.png', confidence=0.9)
print(clk.x)
print(clk.y)
pg.click(clk.x, clk.y)
pg.leftClick(x=clk.x, y=clk.y)
pg.typewrite(['enter'], interval=1)
adobe_install()
I tried clicking, left clicking, and pressing enter. I tested the in other windows like Paint and word and the clicking and they all did indeed click or send "Enter"
This is the error I recieved
File "C:\Users\***\documents\ict\software\New_comp.py", line 77, in adobe_install
bring_to_front(i[0])
File "C:\Users\***\documents\ict\software\New_comp.py", line 41, in bring_to_front
win32gui.SetWindowPos(HWND, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
pywintypes.error: (5, 'SetWindowPos', 'Access is denied.')

Try bringing the window to front & activate it. But you need to put in the window handler
import win32gui
import win32con
def bringTOfront(HWND):
win32gui.ShowWindow(HWND, win32con.SW_RESTORE)
win32gui.SetWindowPos(HWND, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
win32gui.SetWindowPos(HWND, win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
win32gui.SetWindowPos(HWND, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_SHOWWINDOW + win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)

Related

Unable to click inside of a game window with pyautogui/win32api/pydirectinput

I can click on the window, but it doesn't move my character, or interact with anything in game. I've tried moving the mouse around, i've tried doing keyboard inputs, full screen, windowed, etc. I've also tried using screenshots with pyautogui, but no luck. The game i'm trying to use it with was initially released in 2000. Non coding wise i've tried running it as admin, running in windows xp sp 2-3 compatibility mode, disabling desktop composition, etc.
win32api code:
import win32api, win32con
import time
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(573, 841)
# time.sleep(1)
# click(289, 342)
# time.sleep(1)
time.sleep(5)
click(319, 399)
x = win32api.GetCursorPos()
print(x)
error:
win32api.SetCursorPos((x,y)) pywintypes.error: (0, 'SetCursorPos', 'No error message is available')
pyautogui/pydirect input:
import pyautogui
import pydirectinput as p
import time
icon = pyautogui.locateCenterOnScreen('./icon.png', confidence=0.9)
p.click(icon[0], icon[1])
time.sleep(2)
p.press('enter')
this code doesn't throw an error, it completes normally without actually clicking in the game window
First, make sure you are running your script as admin, sometimes if you don't Windows will prevent mouse movement.
Also, try doing this:
def click(x,y):
win32api.SetCursorPos((x, y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)
time.sleep(.01)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0
You have to give it a little bit of time to click or else Python will do it too quickly and the game won't register it.

Simulating mouse click using python and win32api

I am trying to simulate a mouse left click on a window (Samsung Flow) but unfortunately it is not working. When I try on a google chrome window it works, but I have tried on Paint and on Samsung Flow but it does not work. Here is my code:
import win32api
import win32con
import time
import random
def enumHandler(hwnd, lParam):
if win32gui.IsWindowVisible(hwnd):
# if 'Stack Overflow' in win32gui.GetWindowText(hwnd):
if 'Samsung Flow' in win32gui.GetWindowText(hwnd):
print(win32gui.GetWindowText(hwnd))
for _ in range(50):
l_param = win32api.MAKELONG(random.randint(10, 500), random.randint(10, 500))
win32gui.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param)
time.sleep(0.1)
win32gui.PostMessage(hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, l_param)
time.sleep(0.1)
win32gui.EnumWindows(enumHandler, None)
I know that it detects the window as I am printing the detected text, but I do not know why it only work on the Chrome window.
Update
I have tried the following code, to search two windows notepad and browser:
import win32gui
import win32api
import win32con
import time
def enumHandler(hwnd, lParam):
if win32gui.IsWindowVisible(hwnd):
# if 'Notepad' in win32gui.GetWindowText(hwnd):
if 'Stack Overflow' in win32gui.GetWindowText(hwnd):
print(win32gui.GetWindowText(hwnd))
win32gui.SetForegroundWindow(hwnd)
win32api.SendMessage(hwnd, win32con.WM_CHAR, ord("c"), 0)
time.sleep(0.1)
win32gui.EnumWindows(enumHandler, None)
And the result was:
when using on the browser (searching for Stack Overflow window), the window came to foreground and printed the letter c
when using the notepad the window came to foreground but the letter was not printed! and I have no idea why.
Well, I found the problem.
With the example trying to send the letter C to notepad and the chrome browser I assumed that the first hwnd is the right one BUT in some cases, you have to interact with a child window. A window may have more than one child window, so, I will post a code here where you can find the window to interact with.
import win32gui
import win32con
import win32api
import time
def send_char(hwnd, lparam):
s = win32gui.GetWindowText(hwnd)
print("child_hwnd: %d txt: %s" % (hwnd, s))
win32api.PostMessage(hwnd, win32con.WM_CHAR, ord('c'), 0)
time.sleep(5)
return 1
def main():
main_app = 'Untitled - Notepad'
hwnd = win32gui.FindWindow(None, main_app)
if hwnd:
win32gui.EnumChildWindows(hwnd, send_char, None)
main()
With that you can find the child window that you should send the messages to (the code print the window id and name, send the character and wait 5 seconds, so when you notice the character on your window just get the last printed window id and use it instead of the parent window).
I hope it help someone facing the same problem.

Changing desktop background and playing .mp3 file is not working

import ctypes
import winsound
SPI_SETDESKWALLPAPER = 20
while (True):
x = input("Enter Password. ")
if x == "blyat":
print ("motherland russia")
ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, "D:\\VS Code Project\\COMMUNISM.jpg", 0)
winsound.PlaySound("USSR Anthem.mp3", winsound.SND_FILENAME)
When I run the program, I can't hear the .mp3 and the desktop background goes black instead of changing to the image I selected (COMMUNISM.jpg)
Based on the information you provided, I did the following:
Install the module "playsound" and add it to use: (pip install playsound)
from playsound import playsound
Use "playsound('D:\\...\\Ze\\1.mp3')" instead of "winsound.PlaySound("D:\\...\\Ze\\1.mp3", winsound.SND_FILENAME)"
Complete code:
from playsound import playsound
import ctypes
import winsound
SPI_SETDESKWALLPAPER = 20
while (True):
x = input("Enter Password:")
if x == "blyat":
print ("motherland russia")
ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, "D:\\...\\Ze\\1.jpg", 0)
# winsound.PlaySound("D:\\...\\Ze\\1.mp3", winsound.SND_FILENAME)
playsound('D:\\...\\Ze\\1.mp3')
The result of my test on my computer is that the desktop wallpaper was changed and the mp3 played.

Simulating controller dpad button being held down with Python evdev

I'm trying to simulate holding down a DPad button on a controller using Python evdev.
So far I've managed to successfully press a button like so:
import os
import time
from evdev import uinput, ecodes as e, list_devices, InputDevice, ff
dev = InputDevice(str(os.path.realpath("/dev/input/by-id/usb-Sony_Interactive_Entertainment_Wireless_Controller-if03-event-joystick")))
dev.write(e.EV_ABS, e.ABS_HAT0X, 1)
dev.write(e.EV_ABS, e.ABS_HAT0X, 0)
dev.write(e.EV_SYN, 0, 0)
but haven't been able to successfully have the application I'm simulating the input for detect the button held for any amount of time. What I've tried is this (and a couple variations on this)
...
dev.write(e.EV_ABS, e.ABS_HAT0X, 2) # evdev docs say 2 is for holding
dev.write(e.EV_SYN, 0, 0)
time.sleep(2)
dev.write(e.EV_ABS, e.ABS_HAT0X, 0)
dev.write(e.EV_SYN, 0, 0)
What am I doing wrong?

Select text with win32api keybd_event

I'm trying to create a method to select text content of a notepad file using the following keys combination: CTRL+END then SHIFT+HOME
I have the following code to press, hold and release a sequence of keys:
import win32api
import win32con
import win32gui
import time
def keyboard_press_hold_release(*keys):
for k in keys:
win32api.keybd_event(VK_CODE[k], 0, 0, 0)
time.sleep(.05)
for k in keys:
win32api.keybd_event(VK_CODE[k], 0, win32con.KEYEVENTF_KEYUP, 0)
time.sleep(.1)
and call it to combine CTRL+END and SHIFT+HOME:
keyboard_press_hold_release('ctrl', 'end')
keyboard_press_hold_release('shift', 'home')
As result the CTRL+END command is working but the SHIFT+HOME don't select the text, just move the cursor to the begin of line.
What is wrong?
You can use the keyboard module for this purpose. Here is an example:
import keyboard
import time
time.sleep(5) #You need some wait to switch to your window after executing
keyboard.press_and_release("ctrl+end")
keyboard.press_and_release("shift+home")
If Shift+Home doesn't work for you than you can use select the whole text in a single click using Ctrl+A.
keyboard.press_and_release("ctrl+a")

Categories

Resources