pywinauto print_control_identifiers()报错:KeyError与COMError求助
问题:pywinauto调用print_control_identifiers()报错排查思路
问题现象
调用print_control_identifiers()查看1С程序窗口元素树时,出现COMError:
Traceback (most recent call last): File "C:\formation_uploading__tranco\app\tranco.py", line 170, in run_process self.process() File "C:\formation_uploading__tranco\app\tranco.py", line 73, in process window.print_control_identifiers() File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\application.py", line 624, in print_control_identifiers ctrl_names = findbestmatch.get_control_names(ctrl, all_ctrls, txt_ctrls) File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\findbestmatch.py", line 320, in get_control_names non_text_names = get_non_text_control_name(control, allcontrols, textcontrols) File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\findbestmatch.py", line 219, in get_non_text_control_name ctrl_r = ctrl.rectangle() File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\base_wrapper.py", line 367, in rectangle return self.element_info.rectangle File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\uia_element_info.py", line 326, in rectangle bound_rect = self._element.CurrentBoundingRectangle _ctypes.COMError: (-2147220991, 'An event was unable to invoke any of the subscribers', (None, None, None, 0, None)) Process finished with exit code 0
添加depth=3参数时,出现KeyError:
Traceback (most recent call last): File "C:\formation_uploading__tranco\app\tranco.py", line 170, in run_process self.process() File "C:\formation_uploading__tranco\app\tranco.py", line 73, in process window.print_control_identifiers(depth=3) File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\application.py", line 616, in print_control_identifiers all_ctrls = [this_ctrl, ] + this_ctrl.descendants() File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\base_wrapper.py", line 493, in descendants return [self.backend.generic_wrapper_class(element_info) for element_info in desc_elements] File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\base_wrapper.py", line 493, in <listcomp> return [self.backend.generic_wrapper_class(element_info) for element_info in desc_elements] File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\controls\uia_controls.py", line 1102, in __init__ if not self.children() and self.element_info.handle is not None: File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\base_wrapper.py", line 471, in children return [self.backend.generic_wrapper_class(element_info) for element_info in child_elements] File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\base_wrapper.py", line 471, in <listcomp> return [self.backend.generic_wrapper_class(element_info) for element_info in child_elements] File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\controls\uiawrapper.py", line 186, in __new__ return super(UIAWrapper, cls)._create_wrapper(cls, element_info, UIAWrapper) File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\base_wrapper.py", line 126, in _create_wrapper new_class = cls_spec.find_wrapper(element_info) File "C:\Users\admin\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pywinauto\controls\uiawrapper.py", line 160, in find_wrapper wrapper_match = UiaMeta.control_type_to_cls[element.control_type] KeyError: None Process finished with exit code 0
相关代码:
app = Application(backend="uia").connect(title_re="1С:Предприятие - АТК:Управление грузоперевозками") window = app.window(title_re="1С:Предприятие - АТК:Управление грузоперевозками") window.set_focus() button_5 = window.child_window(title="Разобрать", control_type="Button") button_5.click_input() button_6 = window.child_window(title="Перечни", control_type="TabItem") button_6.click_input() window.print_control_identifiers()
已尝试:添加焦点设置、2-30秒等待、重新获取窗口对象、window.wait('ready', timeout=10)、点击按钮后重新连接应用,均无效。
排查与调试思路
- 自定义安全遍历函数:自己实现递归遍历控件的逻辑,在获取控件属性(如rectangle、control_type)时捕获
COMError和KeyError,跳过异常控件,只输出有效信息。示例逻辑:def safe_print_controls(ctrl, indent=0): try: print(f"{' '*indent}{ctrl.control_type} - {ctrl.window_text()}") for child in ctrl.children(): safe_print_controls(child, indent+1) except (_ctypes.COMError, KeyError): print(f"{' '*indent}[SKIPPED] Invalid control") safe_print_controls(window) - 切换backend尝试:将backend从
uia改为win32,因为两种backend的控件识别机制不同,win32对部分传统Windows程序兼容性更好。修改代码开头:app = Application(backend="win32").connect(title_re="1С:Предприятие - АТК:Управление грузоперевозками") - 缩小遍历范围:避免遍历整个窗口,先定位到"Перечни"标签对应的内容容器,只遍历该子控件的元素树,减少接触无效控件的概率。例如:
tab_content = window.child_window(title="Перечни", control_type="TabItem").parent().child_window(control_type="Panel") tab_content.print_control_identifiers() - 升级pywinauto版本:当前使用的pywinauto版本可能存在UIA相关bug,尝试升级到兼容Python3.7的最新版本(如0.6.8),命令:
pip install --upgrade pywinauto==0.6.8 - 用Inspect.exe分析控件:使用Windows SDK自带的Inspect.exe工具,手动查看目标窗口的控件树,确认是否存在控件类型为
None或无法获取边界矩形的控件,定位具体异常控件后,在代码中针对性跳过。 - 过滤控件类型遍历:调用
descendants时指定control_type参数,只遍历已知有效类型的控件,避免触发未知类型的KeyError:valid_ctrl_types = ["Button", "Edit", "TabItem", "Panel", "List"] for ctrl in window.descendants(control_type=valid_ctrl_types): print(ctrl.control_type, ctrl.window_text())
内容的提问来源于stack exchange,提问作者ValeraTheSlayer
相关产品推荐
相关产品推荐

