PyWinAuto trouble clicking the Next Button - python

This code gets the first window from InstallShield.
from pywinauto import application
from pywinauto import findwindows
app = application.Application()
app.start("MyInstallShieldApp.exe")
time.sleep(15)
hwnd = findwindows.find_windows(title=u"InstallShield Wizard", class_name="MsiDialogCloseClass")
print ("|", str(hwnd), "|")
dlg = app.Window_(handle=hwnd).Wait("enabled", timeout=25, retry_interval=0.5)
Now I want to click the Next button. Swapy says that the Next button has the text '&Next >' and the Button number is 1. But none of these click statements have any effect.
dlg.Click("Next")
dlg.Click(coords=(977, 711))
dlg.Click(button="left")

You misapply Click method. It has the next signatire - Click(button=u'left', pressed=u'', coords=(0, 0), double=False, absolute=False)
To click a button, click should be performed on the button object. So you shoud navigate to the button at first.
In your case the code may look something like:
dlg['&Next >'].Click()
Again, please do not guess, read the docs and see the examples

Related

I want to stop a method without completing it's instructions if a certain flag is triggered

I have a method which displays a Toplevel window every few seconds, anyhow if user clicks on dismiss button instead of ok button, the remaining toplevel windows should not be displayed. In below code disAction() is the command for dismiss button
I tried using while loop, it shows 'Not responding' error
def topRequester(self):
if self.dismiss == 0:
self.after(SLEEP_SEC, self.toplevelmaker)
self.after(SLEEP_SEC + SLEEP_SEC, self.toplevelmaker)
self.after(SLEEP_SEC + SLEEP_SEC*2, self.toplevelmaker)
self.after(SLEEP_SEC + SLEEP_SEC*2, self.topRequester)
def disAction(self): # the cycle should be disrupted
self.topwin.withdraw()
self.dismiss = 1

MacOS Pyside2 QSystemTrayIcon, left click/right different functions

I would like to know how to do in python/Pyside2:
Create a QSystemTrayIcon with a custom icon, in which:
If I click left button on it, I do a custom action (just print “left click pressed”). No menu should be shown...
If I click right button on it, a context menu appears with an exit action on it, just to close the program.
On MacOS, maybe not in win nor linux, the menu just opens on mouse press... That's why the need of left and right click differentiations
otherwise both actions will be done with left and right click. See note here: On macOS... since the menu opens on mouse press
I need help just implementing the left and right click differentiations in the following code:
from PySide2 import QtWidgets
import sys
class SystrayLauncher(object):
def __init__(self):
w = QtWidgets.QWidget() #just to get the style(), haven't seen other way
icon = w.style().standardIcon(QtWidgets.QStyle.SP_MessageBoxInformation)
self.tray = QtWidgets.QSystemTrayIcon()
self.tray.setIcon(icon)
self.tray.setVisible(True)
self.tray.activated.connect(self.customAction)
# I JUST WANT TO SEE THE MENU WHEN RIGHT CLICK...
self.trayIconMenu = QtWidgets.QMenu()
self.quitAction = QtWidgets.QAction("&Quit", None, triggered=QtWidgets.QApplication.instance().quit)
self.trayIconMenu.addAction(self.quitAction)
self.tray.setContextMenu(self.trayIconMenu)
# JUST WANNA USE THE ACTION WITH LEFT CLICK
def customAction(self, signal):
print "left click pressed"
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
sl = SystrayLauncher()
sys.exit(app.exec_())
Can anyone help me, please?
you can differentiate the click "reason" and decide what to do. Therefore you will need to add a function like follows:
def right_or_left_click(reason):
if reason == QSystemTrayIcon.ActivationReason.Trigger:
print("Left-click detected")
elif reason == QSystemTrayIcon.ActivationReason.Context:
print("Right-click detected")
elif reason == QSystemTrayIcon.ActivationReason.MiddleClick:
print("Middle-click detected")
else:
print("Unknown reason")
self.tray.activated.connect(right_or_left_click)
Then, you can call the desired function on left-click or middle-click. The right-click is occupied by your context menu :)

How to click button in dialog box using PyWinAuto

I have an batch file that I execute that opens a program. A dialog box then appears which I type into it the username and password credentials
The I print the control identifiers and it lists;
SunAwtDialog - 'Login' (L528, T242, R853, B501)
['SunAwtDialog', 'LoginSunAwtDialog', 'Login']
child_window(title="Login", class_name="SunAwtDialog")
So after reading this post. My understanding was to use window + the button and a click method like so;
dlp.SunAwtDialog['Login'].click()
But this keeps throwing an ElementNotFoundError;
ElementNotFoundError: {'best_match': 'SunAwtDialog', 'top_level_only': False, 'parent': <win32_element_info.HwndElementInfo - 'Login', SunAwtDialog, 2164976>, 'backend': 'win32'}
Below is the full snippet of code;
from pywinauto import application
import time
app = application.Application()
app.start(r"C:\\WINDOWS\system32\cmd.exe", wait_for_idle=False)
dlg = app.top_window()
dlg.type_keys('D:{ENTER}')
dlg.type_keys('cd{SPACE}Software\\client{ENTER}')
dlg.type_keys('run_client.bat{ENTER}')
time.sleep(10)
new_app = application.Application().connect(title="iManager")
dlp = new_app.top_window()
#type username + password
dlp.type_keys('user')
dlp.type_keys('{TAB}')
dlp.type_keys('pass')
#print control identifiers
dlp.print_control_identifiers()
#click login[![enter image description here][1]][1]
dlp.SunAwtDialog['Login'].click()
You can see on the image below the "Login" button I want to be able to click. There is also another button next to the "Server" option, but it is not in my control identifiers
A solution that I use for this is using send_keys. Try this:
from pywinauto.keyboard import send_keys
send_keys("{VK_MENU down}" "l" "{VK_MENU up}")

Python 3 Tkinter Menu widget's callback seems out of sequence

I'm having trouble with the Tkinter Menu widget (no menu button), whereby the callback seems to run out of sequence. Here is a very minimal example:
# Python 3.6.5. Windows 7 x64.
from tkinter import *
root = Tk()
popup = Menu(root, tearoff=0)
popup.add_command(label="test", command=lambda: print("clicked 'test'"))
print("Before post")
popup.post(200,200) # Expecting print output from this (when clicked)
print("After post")
root.mainloop()
print("end of program")
Expected output:
Before post
clicked 'test'
After post
end of program
Actual output:
Before post
After post
clicked 'test' <--- Shouldn't this appear BEFORE previous line?
end of program
I've tried numerous things, without success, such as: popup.wait_window(), popup.update_idletasks(), popup.grab_release(), popup.unpost(), popup.destroy(), tk_popup (instead of Menu), etc.
Any advice would be appreciated.
clicked 'test' <--- Shouldn't this appear BEFORE previous line?
No, it shouldn't. The post only makes the menu appear, it will not wait for the user to select something from the menu. That's just not how tkinter menus are designed to work.
If you need your code to pause until the user makes a selection, you probably need to wait on a variable, and then make sure that all of the menu items set that variable.
I don't get that result on Linux, although apparently the command is supposed to execute. From the docs:
If a -command option is specified for a cascade entry then it is evaluated as a Tcl command whenever the entry is invoked.
My advice is don't try to trigger an event using another trigger. Instead, point both the menu command and whatever you are trying to do programmatically to the same target.
from tkinter import *
def func():
print("clicked 'test'")
root = Tk()
popup = Menu(root, tearoff=0)
popup.add_command(label="test", command=func)
root['menu'] = popup
print("Before post")
func()
print("After post")
root.mainloop()
print("end of program")

A problem with downloading a file with Python

I try to automatically download a file by clicking on a link on the webpage.
After clicking on the link, I get the 'File Download' Window dialog with 'Open', 'Save' and 'Cancel' buttons. I would like to click the Save button.
I use watsup library in the following way:
from watsup.winGuiAuto import *
optDialog = findTopWindow(wantedText="File Download")
SaveButton = findControl(optDialog,wantedClass="Button", wantedText="Save")
clickButton(SaveButton)
For some reason it does not work. The interesting thing is that exactly the same
code works perfectly to click on 'Cancel' button, however it refuses to work with
'Save' or 'Open'.
Anybody knows what I should do?
Thank you very much,
Sasha
Sasha,
It is highly likely that the file dialog you refer to (the Security Warning file download dialog) will NOT respond to windows messages in this manner, for security reasons. The dialog is specifically designed to respond only to a user physically clicking on the OK button with his mouse. I think you will find that the Run button will not work this way either.
Try this:
from watsup.winGuiAuto import *
optDialog = findTopWindow(wantedText="File Download")
SaveButton = findControl(optDialog, wantedClass="Button", wantedText="Submit")
clickButton(SaveButton)
Sasha,
The code at this link is supposed to work. It uses ctypes instead of watsup.winGuiAuto, and relies on win32 calls. Here is the code:
from ctypes import *
user32 = windll.user32
EnumWindowsProc = WINFUNCTYPE(c_int, c_int, c_int)
def GetHandles(title, parent=None):
'Returns handles to windows with matching titles'
hwnds = []
def EnumCB(hwnd, lparam, match=title.lower(), hwnds=hwnds):
title = c_buffer(' ' * 256)
user32.GetWindowTextA(hwnd, title, 255)
if title.value.lower() == match:
hwnds.append(hwnd)
if parent is not None:
user32.EnumChildWindows(parent, EnumWindowsProc(EnumCB), 0)
else:
user32.EnumWindows(EnumWindowsProc(EnumCB), 0)
return hwnds
Here's an example of calling it to click the Ok button on any window that has
the title "Downloads properties" (most likely there are 0 or 1 such windows):
for handle in GetHandles('Downloads properties'):
for childHandle in GetHandles('ok', handle):
user32.SendMessageA(childHandle, 0x00F5, 0, 0) # 0x00F5 = BM_CLICK
It's possible that the save button is not always enabled. While it may look to your eye that it is, a program might see an initial state that you're missing. Check it's state and wait until it's enabled.
[EDIT] But it's possible that Robert is right and the dialog will just ignore you for security reasons. In this case, I suggest to use BeautifulSoup to parse the HTML, extract the URL and download the file in Python using the urllib2 module.

Categories