Skip to content

Instantly share code, notes, and snippets.

@RemcoTukker
Created June 18, 2017 19:36
Show Gist options
  • Save RemcoTukker/8da88d9efdd04112c0e981bc20621828 to your computer and use it in GitHub Desktop.
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?)
# 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