Created
June 18, 2017 19:36
-
-
Save RemcoTukker/8da88d9efdd04112c0e981bc20621828 to your computer and use it in GitHub Desktop.
Monkey patch for pywinauto that adds a first_only parameter to the window function for the UIA backend, in order to work around slow FindAll calls (win10 bug?)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Monkey patch for pywinauto that adds a first_only parameter to the window function | |
# for the UIA backend, in order to work around slow FindAll calls (win10 bug?) | |
# First copy paste this code on your REPL, then do: | |
# d1 = pywinauto.Desktop("uia") | |
# d1.window(first_only=True, title="Calculator").window_text() | |
# Currently only title is supported, but its easy to implement all the others as well, | |
# most importantly title_re | |
def first_child(self): | |
print("Getting first child") | |
child = pywinauto.uia_defines.IUIA().iuia.RawViewWalker.GetFirstChildElement(self._element) | |
if child: | |
return pywinauto.uia_element_info.UIAElementInfo(child) | |
else: | |
return None | |
def next_sibling(self): | |
print("Getting sibling") | |
sibling = pywinauto.uia_defines.IUIA().iuia.RawViewWalker.GetNextSiblingElement(self._element) | |
if sibling: | |
return pywinauto.uia_element_info.UIAElementInfo(sibling) | |
else: | |
return None | |
def find_first_element(first_only=None, | |
title=None, | |
title_re=None, | |
top_level_only=True, | |
backend=None | |
): | |
if backend is None: | |
backend = pywinauto.backend.registry.active_backend.name | |
backend_obj = pywinauto.backend.registry.backends[backend] | |
if not top_level_only: | |
raise NotImplementedError # or can we actually accept this? | |
rootElement = backend_obj.element_info_class() | |
element = None | |
child = rootElement.first_child() | |
while child is not None: | |
print(child.name + " ?= " + title) | |
if child.name == title: | |
# TODO all the other conditions.. | |
# class_name(_re) | |
# title_re | |
# process | |
# visible / enabled / handle / predicate_func / active_only / control_id / control_type / auto_id / framework_id | |
break | |
child = child.next_sibling() | |
return child | |
def new_find_element(**kwargs): | |
if 'first_only' in kwargs and kwargs['first_only'] is True: | |
print("Using patched function to get only the first match") | |
el = pywinauto.findwindows.find_first_element(**kwargs) | |
if el is None: | |
raise pywinauto.findwindows.ElementNotFoundError(kwargs) | |
else: | |
return el | |
else: | |
print("Using original function") | |
return pywinauto.findwindows.original_find_element(**kwargs) | |
import pywinauto | |
pywinauto.uia_element_info.UIAElementInfo.first_child = first_child | |
pywinauto.uia_element_info.UIAElementInfo.next_sibling = next_sibling | |
pywinauto.findwindows.find_first_element = find_first_element | |
pywinauto.findwindows.original_find_element = pywinauto.findwindows.find_element | |
pywinauto.findwindows.find_element = new_find_element |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment