Language/Python

Python - pywinauto, Microsoft Windows GUI 제어 자동화

TechNote.kr 2020. 2. 29. 01:03
728x90

pywinauto

 

WebSite : http://pywinauto.github.io/

Github : https://github.com/pywinauto/pywinauto

Doc : https://pywinauto.readthedocs.io/en/latest

 

Microsoft Windows GUI 제어를 자동화할 수 있는 Python Module 

 

 

설치 

 

> pip3 install pywinauto 

 

(pywinauto 설치시 six, comtypes, pywin32 또한 의존성에 의해 자동 설치된다.)

 

 

사용의 예

 

1) "메모장" 실행 후 "Sample" 문자열을 입력하는 예제

from pywinauto.application import Application
app = Application(backend="uia").start("notepad.exe")
app['Dialog']['Edit'].set_text("Sample")

위에서 사용된 app['Dialog']['Edit'].set_text("Sample") 은 아래와 같이 바꿔서 사용이 가능하다. 

 

app['제목 없음 - Windows 메모장Dialog']['Edit'].set_text("Sample")

app['제목 없음 - Windows 메모장']['Edit'].set_text("Sample")

app['Dia']['Edit'].set_text("Sample")

 

pywinauto.findbestmatch (https://pywinauto.readthedocs.io/en/latest/code/pywinauto.findbestmatch.html)

를 통해 아래 리스트 중 하나를 대략적으로 입력하면 가장 적절한 하위 element 를 골라 준다.

(pywinauto 에서는 magic attribute name 이라고 칭하고 있음.)

 

1) title (window text, name)
2) title and control type
3) control type and number
4) top-left label and control type
5) control type and item text

 

 

2) 이미 실행되어 있는 "메모장"에 "Sample" 문자열을 입력하는 예제

from pywinauto.application import Application
app = Application(backend="uia").connect(path="notepad.exe")
app['Dialog']['Edit'].set_text("Sample")

만약 "메모장"이 실해되어 있지 않다면 아래 에러가 발생한다. 

Traceback (most recent call last):
  File "D:\Python\382_64\lib\site-packages\pywinauto\timings.py", line 436, in wait_until_passes
  File "D:\Python\382_64\lib\site-packages\pywinauto\application.py", line 1458, in process_from_module
    raise ProcessNotFoundError(message)
pywinauto.application.ProcessNotFoundError: Could not find any accessible process with a module of 'notepad.exe'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Python\382_64\lib\site-packages\pywinauto\application.py", line 976, in connect
    self.process = timings.wait_until_passes(
  File "D:\Python\382_64\lib\site-packages\pywinauto\timings.py", line 458, in wait_until_passes
    raise err
pywinauto.timings.TimeoutError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "d:/workspace/PythonStudy/test01.py", line 2, in <module>
    app = Application(backend="uia").connect(path="notepad.exe")
  File "D:\Python\382_64\lib\site-packages\pywinauto\application.py", line 981, in connect
    raise ProcessNotFoundError('Process "{}" not found!'.format(kwargs['path']))
pywinauto.application.ProcessNotFoundError: Process "notepad.exe" not found!

 

 

3) 메뉴 Control 하기 

from pywinauto.application import Application
app = Application(backend="uia").connect(path="notepad.exe")
app['Dialog'].menu_select("파일(F)->열기(O)")

메뉴의 Text 를 이용하여 menu_select 함수로 처리한다. 만약 입력한 Text를 이용해 유사한 메뉴 조차 찾지 못한다면 아래와 같이 선택 가능한 리스트와 함께 에러가 발생한다. 

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\Python\382_64\lib\site-packages\pywinauto\controls\uiawrapper.py", line 723, in menu_select
    menu.item_by_path(path, exact).select()
  File "D:\Python\382_64\lib\site-packages\pywinauto\controls\uia_controls.py", line 1064, in item_by_path
    menu = next_level_menu(menu, menu_items[i], items_cnt == i + 1)
  File "D:\Python\382_64\lib\site-packages\pywinauto\controls\uia_controls.py", line 1044, in next_level_menu
    return self._sub_item_by_text(parent_menu, item_name, exact, is_last)
  File "D:\Python\382_64\lib\site-packages\pywinauto\controls\uia_controls.py", line 1006, in _sub_item_by_text
    sub_item = findbestmatch.find_best_match(name, texts, items)
  File "D:\Python\382_64\lib\site-packages\pywinauto\findbestmatch.py", line 133, in find_best_match
    raise MatchError(items = text_item_map.keys(), tofind = search_text)
pywinauto.findbestmatch.MatchError: Could not find '열기' in 'dict_keys(['새로 만들기(N)', '새 창(W)', '열기(O)...', '저장(S)', '다른 이름으로 저장(A)...', '페이지 설정(U)...', '인쇄(P)...', '끝내기(X)'])'  

 

 

특이사항 

 

Python 3.8.1 에서 import pywinauto 시 아래와 같은 error 발생한다.

Python 3.8.0 이나 3.8.2 사용이 필요하다.

D:\>python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pywinauto
Traceback (most recent call last):
  File "D:\Python\381_64\lib\ctypes\__init__.py", line 123, in WINFUNCTYPE
    return _win_functype_cache[(restype, argtypes, flags)]
KeyError: (<class 'ctypes.HRESULT'>, (<class 'ctypes.c_long'>, <class 'comtypes.automation.tagVARIANT'>, <class 'comtypes.LP_POINTER(IUIAutomationCondition)'>), 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\Python\381_64\lib\site-packages\pywinauto\__init__.py", line 89, in <module>
    from . import findwindows
  File "D:\Python\381_64\lib\site-packages\pywinauto\findwindows.py", line 42, in <module>
    from . import controls
  File "D:\Python\381_64\lib\site-packages\pywinauto\controls\__init__.py", line 36, in <module>
    from . import uiawrapper # register "uia" back-end (at the end of uiawrapper module)
  File "D:\Python\381_64\lib\site-packages\pywinauto\controls\uiawrapper.py", line 47, in <module>
    from ..uia_defines import IUIA
  File "D:\Python\381_64\lib\site-packages\pywinauto\uia_defines.py", line 181, in <module>
    pattern_ids = _build_pattern_ids_dic()
  File "D:\Python\381_64\lib\site-packages\pywinauto\uia_defines.py", line 169, in _build_pattern_ids_dic
    if hasattr(IUIA().ui_automation_client, cls_name):
  File "D:\Python\381_64\lib\site-packages\pywinauto\uia_defines.py", line 50, in __call__
    cls._instances[cls] = super(_Singleton, cls).__call__(*args, **kwargs)
  File "D:\Python\381_64\lib\site-packages\pywinauto\uia_defines.py", line 60, in __init__
    self.UIA_dll = comtypes.client.GetModule('UIAutomationCore.dll')
  File "D:\Python\381_64\lib\site-packages\comtypes\client\_generate.py", line 110, in GetModule
    mod = _CreateWrapper(tlib, pathname)
  File "D:\Python\381_64\lib\site-packages\comtypes\client\_generate.py", line 184, in _CreateWrapper
    mod = _my_import(fullname)
  File "D:\Python\381_64\lib\site-packages\comtypes\client\_generate.py", line 24, in _my_import
    return __import__(fullname, globals(), locals(), ['DUMMY'])
  File "D:\Python\381_64\lib\site-packages\comtypes\gen\_944DE083_8FB8_45CF_BCB7_C477ACB2F897_0_1_0.py", line 1071, in <module>
    IUIAutomation._methods_ = [
  File "D:\Python\381_64\lib\site-packages\comtypes\__init__.py", line 329, in __setattr__
    self._make_methods(value)
  File "D:\Python\381_64\lib\site-packages\comtypes\__init__.py", line 698, in _make_methods
    prototype = WINFUNCTYPE(restype, *argtypes)
  File "D:\Python\381_64\lib\ctypes\__init__.py", line 125, in WINFUNCTYPE
    class WinFunctionType(_CFuncPtr):
TypeError: item 2 in _argtypes_ passes a union by value, which is unsupported.
>>>

 

 

 

 

 

 

 

 

 

728x90