I am trying to automate some GUI stuff in Windows. I open a settings window but when waiting for it to open before continuing, it times out:
from pywinauto import Application
app = Application()
app.start(r"explorer shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}")
app.window(title_re=".*Notification Area Icons*").wait("exists", timeout=20)
app = Application(backend="uia").connect(title_re=".*Notification Area Icons*")
main_dlg = app.window(title_re=".*Notification Area Icons*")
main_dlg.print_control_identifiers()
Even with the timeout at 20 seconds, it times out. However, if I replace app.window(title_re=".*Notification Area Icons*").wait("exists", timeout=20) with sleep(5) (and add the appropriate import) it works fine. I know the window title is correct because it will print out the control ids when using sleep. I've tried using "exists" and "visible" for the wait as well. I think the other options are more strict so I'm not sure why the wait is not working.
It's possible there are few explorer.exe processes. You can try process-agnostic way:
from pywinauto import Desktop
window_wrapper = Desktop(backend="uia").window(title_re=".*Notification Area Icons*").wait("exists", timeout=20)
print(window_wrapper.process_id())
# and compare with print(app.process)
Related
I know I can use time.sleep(), but I need something that would affect whole script.It is automatic test homework and aplication buttons are clicked almost instantly. It is a bit anoying because I cant see if everything is working as supposed(still learning).
import pyautogui
import time
from pywinauto.application import Application
app = Application(backend="uia").start(r"C:\Users\User\Desktop\WPF_RentACar_3maj\WPFRentACar\bin\Debug\WPFRentACar.exe")
pyautogui.FAILSAFE = True
#app.LoginWIndow.print_control_identifiers()
dlg =app.LoginWindow
dlg.MaximizeButton.click()
dlg.MinimizeButton.click()
dlg.MaximizeButton.click()
dlg.Restore.click()
try:
dlg.Edit1.type_keys("123")
dlg.Edit2.type_keys("123")
dlg.LoginButton.click()
dlg.Button1.click()
finally:
print("Cant login with wrong credentials!")
time.sleep(2)
dlg.Edit1.type_keys("'^a{BACKSPACE}")
dlg.Edit2.type_keys("'^a{BACKSPACE}")
dlg.LoginButton1.click()
time.sleep(5)
time.sleep() does stop the whole script. Or are you using threading or python 2? Also can you tell us what you are also trying to automate.
I am trying to send keys to an application running in the background. I want to send 'Alt+f+a' to the background application. I tried type_keys('%fa') from pywinauto but that brings the window to the foreground, I want it to remain in the background.
Here is a bit of what I currently have:
app = Application(backend="win32").connect(path=exePath)
# Open Save As
win = app.window(title_re=appTitle)
win.wait("enabled", timeout=60)
win.type_keys('%fa') #Sends keys, but brings window to foreground
Using type_keys('%fa', set_foreground=False) will send the command to the active window. So, I am using VsCode as my text editor and 'Alt+f+a' gets sent there instead of the target application.
I have tried using send_keystrokes() instead of type_keys(), but this does not complete the command. It does send 'Alt+f' in the background but is not sending the 'a'. I have tried calling 'Alt+f' then 'Alt+a' immediately after (and with a time delay) but sending another 'Alt' just closes the opened file menu.
During my search I have seen PostMessage() from win32gui but have not been able to get that working.
You may try win.send_keystrokes("{VK_MENU DOWN}fa{VK_MENU UP}") to hold Alt for 2 symbols and then release it.
try sending the type_keys parameter set_foreground to False
something like this:
app = Application(backend="win32").connect(path=exePath)
# Open Save As
win = app.window(title_re=appTitle)
win.wait("enabled", timeout=60)
win.type_keys('%fa', set_foreground=False)
or try this method instead: send_keystrokes
like the description says it send keystrokes silently ^^
this works perfectly if window is not minimized, but when window is minimized i am not be able to set the focus on it.
from pywinauto.application import Application
app = Application(backend="uia")
try:
app = app.connect(title_re=".*Bloc*.", visible_only=False)
except:
print("Not visible...")
exit()
app_top_window = app.top_window()
app_top_window.maximize()
How to workaround this and bring the minimized window to the foreground again?
If connect calls works fine, it should work like this:
top_window = app.window(title_re=".*Bloc*.", visible_only=False)
top_window.restore().set_focus() # sometimes .restore() is redundant
app.top_window() is not recommended to use as it sticks to the top window at the moment of .top_window() call. Top window may change at any moment. Also it's for visible top window only.
I have done my form in VB. I cannot access the child window controls. For instance, the alert box appears after submit button is clicked. Here is my code:
# used backend="uia"
import sys
import pyautogui
from pywinauto.application import Application
import time
print("test")
app=Application().start()
app.Form1.Edit4.type_keys("go")
app.Form1.Edit3.type_keys("12")
app.Form1.Male.click()
app.Form1.ComboBox.type_keys("in")
app.Form1.Edit2.type_keys("33")
app.Form1.Submit.click()
app.Form1.Submit.print_control_identifiers()
app.Success.print_control_identifiers()
app.Form1.Success.click()
Success is the name of child window.
you write that you've used backend="uia" but the code Application().start() uses default backend which is "win32". You have to use Application(backend="uia").start() to choose "uia".
Note: for "win32" backend the alert window is a top-level window. So you need app.Success.OK.click() to click OK button on it. For backend="uia" alert window will be child of "Form1".
EDIT: this code should work:
app.Form1.Success.OKButton.click() # alias of .invoke();
# see IsInvokePatternSupported == True in Inspect.exe
# or
app.Form1.Success.OKButton.click_input() # real click
EDIT2: It may be timing issue. pywinauto has default timeout 5 seconds waiting for dialog appearance. If dialog appears after more than 5 seconds, you need something like that: app.Form1.Success.wait('visible', timeout=20).
Another possible issue is blocking behavior of app.Form1.Submit.click() which calls InvokePattern. Sometimes this pattern implementation waits for dialog closing (this is app side issue though). You might have to change this to app.Form1.Submit.click_input().
Using Win32GUI and Watsup, I'm writing a bit of Python code to automate a search across a database that is accessed through a program that doesn't come with an interface for it. As such, I can take a string from a list and then input it into the search box and press 'lookup'.
However, when the search returns more than 1000 results, the program throws a warning dialog --which is simply a notification of the number of results--which halts the execution of the Python code. I can't get the code to progress past the line where it presses lookup.
At a guess, this would be because it doesn't expect a window or know how to handle a warning--but I don't either, other than manually accepting it. Below is the relevent sample of code, though it's probably not very enlightening. After "clickButton(LookupButton)", the execution halts.
LookupButtonlocation = elemstring.find("Lookup", AuthNameFieldlocation) - 15
#Use Regex search to find handles
number_regex = re.compile(';(\d+);')
AuthNameEdit = int(number_regex.search(elemstring[AuthNameFieldlocation:]).group(1))
LookupButton = int(number_regex.search(elemstring[LookupButtonlocation:]).group(1))
#Input new Author into Edit Field
setEditText(AuthNameEdit, "John Campbell")
#Click lookup button
clickButton(LookupButton)
I'm not a WATSUP user, but I do something very similar using pywinauto - in my case I'm running a number of automated tests that open various 3rd party programs that, in a similar way, throw up inconvenient warning dialogs. It's a bit difficult to deal with dialogs that you don't know about, however if you do know which dialogs appear, but not when they appear, you can start a thread to just deal with those pop-ups. The following is a simple example from what I'm doing, and uses pywinauto but you could adapt the approach for WATSUP:
import time
import threading
class ClearPopupThread(threading.Thread):
def __init__(self, window_name, button_name, quit_event):
threading.Thread.__init__(self)
self.quit_event = quit_event
self.window_name = window_name
self.button_name = button_name
def run(self):
from pywinauto import application, findwindows
while True:
try:
handles = findwindows.find_windows(title=self.window_name)
except findwindows.WindowNotFoundError:
pass #Just do nothing if the pop-up dialog was not found
else: #The window was found, so click the button
for hwnd in handles:
app = application.Application()
app.Connect(handle=hwnd)
popup = app[self.window_name]
button = getattr(popup, self.button_name)
button.Click()
if self.quit_event.is_set():
break
time.sleep(1) #should help reduce cpu load a little for this thread
Essentially this thread is just an infinite loop that looks for a pop-up window by name, and if it finds it, it clicks on a button to close the window. If you have many pop-up windows you can open one thread per popup (bug that's not overly efficient, though). Because it's an infinite loop, I have the thread looking to see if an event is set, to allow me to stop the thread from my main program. So, in the main program I do something like this:
#Start the thread
quit_event = threading.Event()
mythread = ClearPopupThread('Window Popup Title', 'Yes button', quit_event)
# ...
# My program does it's thing here
# ...
# When my program is done I need to end the thread
quit_event.set()
This is not necessarily the only way to deal with your issue, but is a way that's worked for me. Sorry I can't really help you much with dealing with WATSUP (I always found pywinauto a bit easier to use), but I noticed on the WATSUP homepage (http://www.tizmoi.net/watsup/intro.html), Example 2 does something similar without using threads, i.e., looks for a named window and clicks a specific button on that window.