No control identifiers using pywinauto - python

I have a problem with print_control_identifiers() using pywinauto.
I start my test by opening test app.
window1 = Application(backend="uia")
window1.start("C:/Program Files (x86)/.../App.exe")
window1.Dialog.print_control_identifiers()
window1.Dialog.Run.click()
This is ok, I have output with all elements in this dialog - all buttons, boxes, labels etc.
After click() my dialog disappears and i need to connect to new window, so:
window2 = Application().connect(title="new-window")
window2.AppDialog.print_control_identifiers()
And there is my problem: output not contains any elements, just simple:
HwndWrapper[App.exe;App;c002ffc1-d144-4cd1-8ab0-afe5031cb9ea] - 'new-window' (L-8, T-8, R1928, B1058)
['new-window', 'HwndWrapper[App.exe;c002ffc1-d144-4cd1-8ab0-afe5031cb9ea]', 'new-windowHwndWrapper[App.exe;c002ffc1-d144-4cd1-8ab0-afe5031cb9ea]']
child_window(title="new-window", class_name="HwndWrapper[App.exe;c002ffc1-d144-4cd1-8ab0-afe5031cb9ea]")
How to print all control identifiers of this new window?
Whatever I try to find, eg. window2.AppDialog.Login.click() i have pywinauto.findwindows.ElementNotFoundError.

Looks like you forgot to use backend="uia" for Application object in this line:
window2 = Application().connect(title="new-window")
It should look so:
window2 = Application(backend="uia").connect(title="new-window")
If the first window spawns a child process, you have to connect to this process which contains new window. We have plans to implement child process detection by Application object in the future. Now it should be handled manually.

Try this method:
pid= application.process_from_module('toolName.exe')
app= Application(backend="uia").connect(process=pid)
handle = app.window(title_re="new-windowName")
handle.print_control_identifiers()
Or just use Inspect.exe to get all the details if you dont need print it explicitly.
Inspect.exe can get you all the details of any element you focus on..

Related

Sometimes I can not find a window by ParentDlg.child_window()

I have just started learning python. Now my work is trying to use pywinauto to do some auto tests. Sometimes I can get one dialog by ParentDlg.child_window(**criterion), sometimes not.
You can think my application(PageManager.exe) has two buttons, [Page1] button and [Page2] button. When application is started, you can click button to start Page.exe process. That means there are two Page.exe at the same time. When Page.exe is started, it starts ImageCalculate.exe. So there are two ImageCalculate.exe two. The parent dialog of ImageCalculate.exe is Page.exe.
When you click [Page1] button, the Page.exe (used for Page1) is displayed and Page.exe (used for Page2) is hid. When you click [Page2] button, the Page.exe (used for Page2) is displayed and Page.exe (used for Page1) is hid.
My problem is when one Page.exe is displayed, such as Page.exe(used for Page1). I can find main dialog of Page.exe by ParentDlg = Desktop(backend="uia").window(best_match="Page1"). After that, I use psutil.pids() and process name "ImageCalculate.exe" to get two PIDs of ImageCalculate.exe, for example, one is 1234, another is 5678. Please attention, two ImageCalculate.exe have almost the same property, same title, class name and so on.
At last I try to get the main dialog of ImageCalculate.exe by ParentDlg.child_window(**criterion).
But according to my test, sometimes I can get main dialog and continue to operate its controls, sometimes not. I don’t know why, I hope someone can help me or provide another way to get the main dialog of ImageCalculate.exe. Because I have the PID of ImageCalculate.exe, maybe I can get the Process’s main dialog by PID? And then maybe I can check this dialog is displayed or not to confirm this dialog belongs to which Page.exe(If this dialog is displayed, I think this dialog belongs to Page1’s Page.exe’s ImageCalculate.exe).
ParentDlg = Desktop(backend="uia").window(best_match="Page1")
// pids contains two pid of ImageCalculate.exe
for pid in pids:
try:
criterion = {}
criterion['class_name_re'] = "AfxFrameOrView*"
criterion['process']=pid
ImageCalculate_dialog = parent.child_window(**criterion)
# I think if ImageCalculate_dialog.writable_props is successful.
# Page1’s Page.exe’s ImageCalculate.exe's main dialog is found.
# But some times ImageCalculate_dialog.writable_props is failed two times and throws ElementNotFoundError
_cname = ImageCalculate_dialog.writable_props
except pywinauto.findwindows.ElementNotFoundError:
continue
else:
return ImageCalculate_dialog
# Now I am trying to use following codes to get main dialog
ImageCalculateApp = Application().connect(process=pid)
dialogs = ImageCalculateApp.windows()
for dialog in dialogs:
print(dialog)
# When I check print result in console
# I can find "hwndwrapper.DialogWrapper - 'ImageCalculate - Untitled',Afx:00400000:b:00010003:00000006:003908A5"
# But I don't know how to use hwndwrapper.DialogWrapper object,
# who could tell me how to use this object or give me some documents about this object?

GUI automation using pywinauto python. Attribute error , menu_select() missing error in uaicontrols.py

I'm tring to automate a windows gui mouse click of a check box in properties of a printer.
I get to this by starting print management mmc, right clicking on "G23XnQ2E (local)" from "Print Servers" drop down in the left pane and selecting properties, switching to "security tab" and i finally want to select the checkbox against manage printer option. This can also be achieved by directly clicking on the action menu and selecting properties, provided that i have selected "G23XnQ2E (local)" from the printer servers.
I have tried all the possible ways that I can thing of but always end up getting the many errors like "raise AttributeError", "menu_select", "select()", "click()" - "missing".
my code is like say:
from pywinauto import Application
Application().start(r'mmc printmanagement.msc')
app = Application(backend="uia").connect(path='mmc.exe')
app.PrintManagement.dump_tree()
app.dialog.pane1.pane5.pane6.menu.menu_select("Action -> Properties")
#app.dialog.menu_select("Action -> Properties")
#app.dialog.pane1.pane5.pane6.menu.ActionMentuitem.select()
#app.dialog.pane1.pane5.pane6.menu.ActionMentuitem.click()
How to fix the problem?
menu_select is good for main menu like "File->Open". It doesn't work for popup/context menus. This is my code working on my PC (name of print server has been changed to yours):
from pywinauto import Application
Application().start(r'mmc printmanagement.msc')
app = Application(backend="uia").connect(path='mmc.exe')
#app.PrintManagement.dump_tree()
print_servers = app.PrintManagement.child_window(title="Print Servers", control_type="TreeItem")
print_servers.select() # it expands the subtree
# call popup menu
print_servers.child_window(title="G23XZNQ2E (local)", control_type="TreeItem").right_click_input()
# alternative way to call popup menu
#print_servers.child_window(title_re=".*\(local\)$", control_type="TreeItem").right_click_input()
# select "Properties..." menu item
app.ContextMenu.child_window(title="Properties...", control_type="MenuItem").select()
#app.PrintManagement.Print_Server_Properties.dump_tree()
app.PrintManagement.Print_Server_Properties.TabControl.select('Security')
app.PrintManagement.Print_Server_Properties.child_window(title="Allow Manage Printers", control_type="CheckBox").toggle()
All child_window specifications have been copied from dump_tree() outputs. Some windows are children of main window, but context menu is a top level one. This is not a documented experience, but we're working on a recorder feature planned this year as Beta. So it will be much easier to generate a script without thinking about hierarchy structure so much.

Python 2.7: Close a dialog without exiting the entire application

I'm running a script coded in python from a scripts menu in a desktop application. It's basically a giant macro that I wrote and added a GUI to. I'm pretty sure the GUI is a really old one that my desktop app uses called dialogKit from MIT.
GitHub still has it here.
The problem is the word "stop" at the very end of the dialog code.
I keep getting a "stop is undefined" message, which I understand, but I've tried everything to close the dialog and if I use exit(), sys.exit(), I don't get an error, but it also closes my entire desktop app.
I need to close the dialog and keep the software open.
The limited dialog documentation for what I'm using can be found here.
(you might have to click on the Dialog section. Their site uses frames.)
class MyDialog:
def __init__(self):
self.d = Dialog(self)
self.d.size = Point(300, 340)
self.d.Center()
self.d.title = "Halftone" #<----- Title of the dialogue
self.d.AddControl(STATICCONTROL, Rect(aIDENT, aIDENT, aIDENT, aIDENT), "frame", STYLE_FRAME)
# more controls and methods..
def on_ok(self, code):
return 1
def on_cancel(self, code):
print "blah"
def Run(self):
return self.d.Run()
d = MyDialog()
if d.Run()!= 1:
stop
I just need a way to change stop to something that 1) will prevent the script from running, and 2) close the dialog without quitting the entire application. This is the functionality of a typical "cancel" button, which is what I want.
Another option is the method called on_cancel(), which I also tried and could get the event itself to work, but still the entire application quits with any kind of exit().
The docs show a method called End(), which claims to terminate the dialog object, but I've tried and failed to get that to work either.
Okay, I'm posting an answer because I think I have a handle on your problem.
Try replacing stop with:
d.d.End()
If that works, you might want to try putting:
self.d.End()
inside of the on_cancel function in your class. That should close the dialogue without closing your program.

Can I add element in code so that I could get it later through Gtk.Builder()?

I use Python 3+PyGObjects+Gtk.Builder
I have some window, what I create from glade:
builder = Gtk.Builder()
builder.add_from_file("main.ui")
I create some widgets and add them(i see it in window):
switch = Gtk.Switch()
switch.set_name('test')
hBox = Gtk.HBox()
hBox.pack_start(switch, True, True, 10)
window = builder.get_object("MainWindow")
window.add(hBox)
At another part of program I do not have access to "switch", but have to "builder". I try:
switch = builder.get_object('test')
switch_active = switch.get_active()
But receive error:
AttributeError: 'NoneType' object has no attribute 'get_active'
How I can get it from "builder"?
You can't. Builder can only give you objects defined in the ui file.
You should modify your program so that you do have access to switch in the part that needs to get the active value.
Another option is to name your container in ui file, retrieve the container in code using get_object and set your new widget as its child. Then, retrieve later the container and ask for its child.
Yet another option: if you require to modify one attribute of a widget at runtime (quite common, for example, for combo boxes and treeviews), instead of creating it in code and append it later, you better retrieve it from the ui a changed it. You can particularly changed the visibility attribute, so it can be shown depending of context.
In conclusion is very uncommon to have to create widgets in code when using GtkBuilder. Even for contributed widgets you can create a catalog. You can also have many GtkBuilders if you don't want to load all yours screens at once.

How to prevent a double execution of a single-click event when actually trying to trigger a double click event?

I am creating a gtk (pygtk) based GUI file browser on python using IconView. It has two signals - selection-changed which is triggered when an image is selected by single click and item-activated which is triggered when a double-click is performed . I need both the signals in my program , selection-changed to select folders to cut/copy and item-activated to navigate child folders and files.
However, double-clicking generates two selection-changed signals and one item-activated signal. I only need the item-activated signal to be generated.
Hence the question.
The second single-click and the double-click event should arrive simultaniously.
You can use glib.timeout_add(interval, callback, ...) to execute all the single-clicks after a milli second (or increase it).
If within some time a double-click occurred then you do not execute the single-click event.
Implementation hints: use a variable so save when the last double-click occurred and a variable for the last click using time.time().
If the double-click and single-click are very close, do not execute the singe-click code.
Due to the use of the timeout, the single-click always executes after the double-click.
Why not keep track which item is selected? Ignore selection-changed on second click since selection won't have changed. Here is an example from pytk FAQs modified to handle this case...
import gtk
import gtk.gdk
current_path = []
current_path.append(None)
def on_selection_changed(iconview, current_path):
if iconview.get_selected_items():
if cmp(current_path[0], iconview.get_selected_items()[0]):
print "selection-changed"
current_path[0] = iconview.get_selected_items()[0]
def on_item_activated(iconview, path):
print "item-activated"
# First create an iconview
view = gtk.IconView()
view.connect("selection-changed", on_selection_changed, current_path)
view.connect("item-activated", on_item_activated)
# Create a store for our iconview and fill it with stock icons
store = gtk.ListStore(str, gtk.gdk.Pixbuf)
for attr in dir(gtk):
if attr.startswith('STOCK_'):
stock_id = getattr(gtk, attr)
pixbuf = view.render_icon(stock_id,
size=gtk.ICON_SIZE_BUTTON, detail=None)
if pixbuf:
store.append(['gtk.%s' % attr, pixbuf])
# Connect our iconview with our store
view.set_model(store)
# Map store text and pixbuf columns to iconview
view.set_text_column(0)
view.set_pixbuf_column(1)
# Pack our iconview into a scrolled window
swin = gtk.ScrolledWindow()
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin.add_with_viewport(view)
swin.show_all()
# pack the scrolled window into a simple dialog and run it
dialog = gtk.Dialog('IconView Demo')
close = dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_NONE)
dialog.set_default_size(400,400)
dialog.vbox.pack_start(swin)
dialog.run()

Categories

Resources