Contents

What is pywinauto

© Mark Mc Mahon and Contributors, 2006-2018

Released under the BSD 3-clause license

What is it?

pywinauto是一组用于自动化Microsoft Windows GUI的python模块。 最简单的是,它允许您将鼠标和键盘操作发送到Windows对话框和控件。

Installation

  • Just run pip install pywinauto

Manual installation

To check you have it installed correctly Run Python

>>> from pywinauto.application import Application
>>> app = Application(backend="uia").start("notepad.exe")
>>> app.UntitledNotepad.type_keys("%FX")

How does it work

入门指南中描述了核心概念。

通过每个类的属性访问(__ getattribute __)完成了很多工作。 例如,当您获得Application或Dialog对象的属性时,它会分别查找对话框或控件。

myapp.Notepad # looks for a Window/Dialog of your app that has a title 'similar'
              # to "Notepad"

myapp.PageSetup.OK # looks first for a dialog with a title like "PageSetup"
                   # then it looks for a control on that dialog with a title
                   # like "OK"

此属性解析会延迟(使用默认超时),直到成功为止。 因此,例如,如果您选择菜单选项,然后查找结果对话框,例如

app.UntitledNotepad.menu_select("File->SaveAs")
app.SaveAs.ComboBox5.select("UTF-8")
app.SaveAs.edit1.set_text("Example-utf8.txt")
app.SaveAs.Save.click()

在第2行,执行此行时可能无法打开SaveAs对话框。 所以会发生什么,我们要等到我们有一个控件要解决之前解决对话框。 此时,如果我们找不到带有ComboBox5控件的SaveAs对话框,那么我们会等待很短的时间再试一次,这会重复到最大时间(目前为5秒!)

这是为了避免必须明确使用time.sleep或“wait”函数。

如果您的应用程序执行长时间操作,则新对话框可能会在以后显示或消失。 你可以等待它的新状态

app.Open.Open.click() # opening large file
app.Open.wait_not('visible') # make sure "Open" dialog became invisible
# wait for up to 30 seconds until data.txt is loaded
app.window(title='data.txt - Notepad').wait('ready', timeout=30)

一些类似的工具用于比较

  • Python tools
    • PyAutoGui - 一个流行的跨平台库(具有基于图像的搜索,没有基于文本的控件操作)。
    • Lackey - Sikuli的纯Python替代品(基于图像模式匹配)。
    • AXUI - MS UI Automation API的一个包装器。
    • winGuiAuto - 使用Win32 API的另一个模块。

Why write yet another automation tool if there are so many out there?

There are loads of reasons :-)

Takes a different approach:

大多数其他工具不是面向对象的,你最终写的东西如下:

window = findwindow(title = "Untitled - Notepad", class = "Notepad")
SendKeys(window, "%OF")  # Format -> Font
fontdialog  = findwindow("title = "Font")
buttonClick(fontdialog, "OK")

我希望创造一些更加用户友好(和pythonic)的东西。 例如,上面的翻译将是:

win = app.UntitledNotepad
win.menu_select("Format->Font")
app.Font.OK.click()
Python makes it easy:
Python是一种很棒的编程语言,但没有自动化工具是Pythonic(极少数库是用Python实现的)。
Localization as a main requirement:

Mark:

“I work in the localization industry and GUI automation is used extensively as often all you need to do is ensure that your UI behaves and is correct with respect to the Source UI. This is actually an easier job then for testing the original source UI.

But most automation tools are based off of coordinates or text of the controls and these can change in the localized software. So my goal ( though not yet implemented) is to allow scripts to run unchanged between original source language (often English) and the translated software (Japanese, German, etc).”

Getting Started Guide

Once you have installed pywinauto - how do you get going? The very first necessary thing is to determine which accessibility technology (pywinauto’s backend) could be used for your application.

The list of supported accessibility technologies on Windows:

  • Win32 API (backend="win32") - a default backend for now
    • MFC,VB6,VCL,简单的WinForms控件和大多数旧的遗留应用程序
  • MS UI Automation (backend="uia")
    • WinForms,WPF,商店应用,Qt5,浏览器

    注意:Chrome在启动之前需要 - force-renderer-accessibility cmd标志。 由于comtypes Python库限制,不支持自定义属性和控件。

Not supported: Java AWT/Swing, GTK+, Tkinter.

到目前为止,Linux上的AT SPI和Apple Accessibility API都是长期计划。

GUI Objects Inspection / Spy Tools

如果您仍然不确定哪个后端最适合您,请尝试使用免费提供的对象检查/间谍工具:从GitHub repo gui-inspect-tool下载它们。

  • Spy++包含在MS Visual Studio发行版(甚至是Express或Community)中,可通过“开始”菜单访问。 It uses Win32 API. 这意味着如果Spy++可以显示所有控件,那么“win32”后端就是您所需要的。 AutoIt窗口信息工具是一种间谍克隆。

  • Inspect.exe是Microsoft创建的另一个很棒的工具。 它包含在Windows SDK中,因此可以在x64 Windows上的以下位置找到它:

    C:\Program Files (x86)\Windows Kits\<winver>\bin\x64
    

    将Inspect.exe切换到UIA模式(使用MS UI Automation)。 如果它可以显示比Spy更多的控件及其属性,那么可能是“uia”后端是你的选择。

如果所有检测工具都看不到某些或所有控件,则仍然可以通过使用基本模块鼠标键盘生成鼠标和键盘事件来控制应用程序。

Entry Points for Automation

所以你有一个应用程序,你知道它支持上面提到的一种可访问性技术。 What’s the next?

首先,您应该启动应用程序或连接到现有的应用程序实例。 可以使用Application对象完成。 这不仅仅是subprocess.Popen的克隆,而是进一步自动化的入口点,通过过程边界限制所有范围。 控制应用程序的潜在极少数实例很有用(您使用一个不打扰另一个实例的实例)。

from pywinauto.application import Application
app = Application(backend="uia").start('notepad.exe')

# describe the window inside Notepad.exe process
dlg_spec = app.UntitledNotepad
# wait till the window is really open
actionable_dlg = dlg_spec.wait('visible')

如果您想跨越流程边界(例如,Win10计算器令人惊讶地在多个流程中绘制其小部件),您的入口点是Desktop对象。

from subprocess import Popen
from pywinauto import Desktop

Popen('calc.exe', shell=True)
dlg = Desktop(backend="uia").Calculator
dlg.wait('visible')

ApplicationDestop对象都是特定于后端的。 无需在后续操作中明确使用后端名称。

Window Specification

这是高级pywinauto API的核心概念。 您可以近似或更详细地描述任何窗口或控件,即使它尚不存在或已经关闭。 窗口规范还保留有关将用于获得真实窗口或控件的匹配/搜索算法的信息。

让我们创建一个详细的窗口规范:

>>> dlg_spec = app.window(title='Untitled - Notepad')

>>> dlg_spec
<pywinauto.application.WindowSpecification object at 0x0568B790>

>>> dlg_spec.wrapper_object()
<pywinauto.controls.win32_controls.DialogWrapper object at 0x05639B70>

实际窗口查找由wrapper_object()方法执行。 它返回实际现有窗口/控件的一些包装器或引发ElementNotFoundError 此包装器可以通过发送操作或检索数据来处理窗口/控件。

但Python可以隐藏这个wrapper_object()调用,以便您在生产中拥有更紧凑的代码。 以下陈述完全相同:

dlg_spec.wrapper_object().minimize() # while debugging
dlg_spec.minimize() # in production

创建窗口规范有许多可能的标准。 These are just a few examples.

# can be multi-level
app.window(title_re='.* - Notepad$').window(class_name='Edit')

# can combine criteria
dlg = Desktop(backend="uia").Calculator
dlg.window(auto_id='num8Button', control_type='Button')

可以在pywinauto.findwindows.find_elements()函数中找到可能的标准列表。

Attribute Resolution Magic

Python通过动态解析对象属性简化了创建窗口规范。 但是一个属性名称与任何变量名称具有相同的限制:没有空格,逗号和其他特殊符号。 但幸运的是pywinauto使用“最佳匹配”算法来查找拼写错误和小变化。

app.UntitledNotepad
# is equivalent to
app.window(best_match='UntitledNotepad')

通过类似字典的项目访问,可以使用Unicode字符和特殊符号。

app['Untitled - Notepad']
# is the same as
app.window(best_match='Untitled - Notepad')

How to know magic attribute names

如何将“最佳匹配”金牌附加到控件上有几个原则。 因此,如果窗口规范接近其中一个名称,您将获得成功的名称匹配。

  1. By title (window text, name): app.Properties.OK.click()
  2. By title and control type: app.Properties.OKButton.click()
  3. By control type and number: app.Properties.Button3.click() (Note: Button0 and Button1 match the same button, Button2 is the next etc.)
  4. By top-left label and control type: app.OpenDialog.FileNameEdit.set_text("")
  5. By control type and item text: app.Properties.TabControlSharing.select("General")

通常并非所有这些匹配的名称都可以同时使用。 要检查指定对话框的这些名称,可以使用print_control_identifiers()方法。 可能的“best_match”名称显示为树中每个控件的Python列表。 也可以从方法输出中复制更详细的窗口规范。 Say app.Properties.child_window(title="Contains:", auto_id="13087", control_type="Edit").

>>> app.Properties.print_control_identifiers()

Control Identifiers:

Dialog - 'Windows NT Properties'    (L688, T518, R1065, B1006)
[u'Windows NT PropertiesDialog', u'Dialog', u'Windows NT Properties']
child_window(title="Windows NT Properties", control_type="Window")
   |
   | Image - ''    (L717, T589, R749, B622)
   | [u'', u'0', u'Image1', u'Image0', 'Image', u'1']
   | child_window(auto_id="13057", control_type="Image")
   |
   | Image - ''    (L717, T630, R1035, B632)
   | ['Image2', u'2']
   | child_window(auto_id="13095", control_type="Image")
   |
   | Edit - 'Folder name:'    (L790, T596, R1036, B619)
   | [u'3', 'Edit', u'Edit1', u'Edit0']
   | child_window(title="Folder name:", auto_id="13156", control_type="Edit")
   |
   | Static - 'Type:'    (L717, T643, R780, B658)
   | [u'Type:Static', u'Static', u'Static1', u'Static0', u'Type:']
   | child_window(title="Type:", auto_id="13080", control_type="Text")
   |
   | Edit - 'Type:'    (L790, T643, R1036, B666)
   | [u'4', 'Edit2', u'Type:Edit']
   | child_window(title="Type:", auto_id="13059", control_type="Edit")
   |
   | Static - 'Location:'    (L717, T669, R780, B684)
   | [u'Location:Static', u'Location:', u'Static2']
   | child_window(title="Location:", auto_id="13089", control_type="Text")
   |
   | Edit - 'Location:'    (L790, T669, R1036, B692)
   | ['Edit3', u'Location:Edit', u'5']
   | child_window(title="Location:", auto_id="13065", control_type="Edit")
   |
   | Static - 'Size:'    (L717, T695, R780, B710)
   | [u'Size:Static', u'Size:', u'Static3']
   | child_window(title="Size:", auto_id="13081", control_type="Text")
   |
   | Edit - 'Size:'    (L790, T695, R1036, B718)
   | ['Edit4', u'6', u'Size:Edit']
   | child_window(title="Size:", auto_id="13064", control_type="Edit")
   |
   | Static - 'Size on disk:'    (L717, T721, R780, B736)
   | [u'Size on disk:', u'Size on disk:Static', u'Static4']
   | child_window(title="Size on disk:", auto_id="13107", control_type="Text")
   |
   | Edit - 'Size on disk:'    (L790, T721, R1036, B744)
   | ['Edit5', u'7', u'Size on disk:Edit']
   | child_window(title="Size on disk:", auto_id="13106", control_type="Edit")
   |
   | Static - 'Contains:'    (L717, T747, R780, B762)
   | [u'Contains:1', u'Contains:0', u'Contains:Static', u'Static5', u'Contains:']
   | child_window(title="Contains:", auto_id="13088", control_type="Text")
   |
   | Edit - 'Contains:'    (L790, T747, R1036, B770)
   | [u'8', 'Edit6', u'Contains:Edit']
   | child_window(title="Contains:", auto_id="13087", control_type="Edit")
   |
   | Image - 'Contains:'    (L717, T773, R1035, B775)
   | [u'Contains:Image', 'Image3', u'Contains:2']
   | child_window(title="Contains:", auto_id="13096", control_type="Image")
   |
   | Static - 'Created:'    (L717, T786, R780, B801)
   | [u'Created:', u'Created:Static', u'Static6', u'Created:1', u'Created:0']
   | child_window(title="Created:", auto_id="13092", control_type="Text")
   |
   | Edit - 'Created:'    (L790, T786, R1036, B809)
   | [u'Created:Edit', 'Edit7', u'9']
   | child_window(title="Created:", auto_id="13072", control_type="Edit")
   |
   | Image - 'Created:'    (L717, T812, R1035, B814)
   | [u'Created:Image', 'Image4', u'Created:2']
   | child_window(title="Created:", auto_id="13097", control_type="Image")
   |
   | Static - 'Attributes:'    (L717, T825, R780, B840)
   | [u'Attributes:Static', u'Static7', u'Attributes:']
   | child_window(title="Attributes:", auto_id="13091", control_type="Text")
   |
   | CheckBox - 'Read-only (Only applies to files in folder)'    (L790, T825, R1035, B841)
   | [u'CheckBox0', u'CheckBox1', 'CheckBox', u'Read-only (Only applies to files in folder)CheckBox', u'Read-only (Only applies to files in folder)']
   | child_window(title="Read-only (Only applies to files in folder)", auto_id="13075", control_type="CheckBox")
   |
   | CheckBox - 'Hidden'    (L790, T848, R865, B864)
   | ['CheckBox2', u'HiddenCheckBox', u'Hidden']
   | child_window(title="Hidden", auto_id="13076", control_type="CheckBox")
   |
   | Button - 'Advanced...'    (L930, T845, R1035, B868)
   | [u'Advanced...', u'Advanced...Button', 'Button', u'Button1', u'Button0']
   | child_window(title="Advanced...", auto_id="13154", control_type="Button")
   |
   | Button - 'OK'    (L814, T968, R889, B991)
   | ['Button2', u'OK', u'OKButton']
   | child_window(title="OK", auto_id="1", control_type="Button")
   |
   | Button - 'Cancel'    (L895, T968, R970, B991)
   | ['Button3', u'CancelButton', u'Cancel']
   | child_window(title="Cancel", auto_id="2", control_type="Button")
   |
   | Button - 'Apply'    (L976, T968, R1051, B991)
   | ['Button4', u'ApplyButton', u'Apply']
   | child_window(title="Apply", auto_id="12321", control_type="Button")
   |
   | TabControl - ''    (L702, T556, R1051, B962)
   | [u'10', u'TabControlSharing', u'TabControlPrevious Versions', u'TabControlSecurity', u'TabControl', u'TabControlCustomize']
   | child_window(auto_id="12320", control_type="Tab")
   |    |
   |    | TabItem - 'General'    (L704, T558, R753, B576)
   |    | [u'GeneralTabItem', 'TabItem', u'General', u'TabItem0', u'TabItem1']
   |    | child_window(title="General", control_type="TabItem")
   |    |
   |    | TabItem - 'Sharing'    (L753, T558, R801, B576)
   |    | [u'Sharing', u'SharingTabItem', 'TabItem2']
   |    | child_window(title="Sharing", control_type="TabItem")
   |    |
   |    | TabItem - 'Security'    (L801, T558, R851, B576)
   |    | [u'Security', 'TabItem3', u'SecurityTabItem']
   |    | child_window(title="Security", control_type="TabItem")
   |    |
   |    | TabItem - 'Previous Versions'    (L851, T558, R947, B576)
   |    | [u'Previous VersionsTabItem', u'Previous Versions', 'TabItem4']
   |    | child_window(title="Previous Versions", control_type="TabItem")
   |    |
   |    | TabItem - 'Customize'    (L947, T558, R1007, B576)
   |    | [u'CustomizeTabItem', 'TabItem5', u'Customize']
   |    | child_window(title="Customize", control_type="TabItem")
   |
   | TitleBar - 'None'    (L712, T521, R1057, B549)
   | ['TitleBar', u'11']
   |    |
   |    | Menu - 'System'    (L696, T526, R718, B548)
   |    | [u'System0', u'System', u'System1', u'Menu', u'SystemMenu']
   |    | child_window(title="System", auto_id="MenuBar", control_type="MenuBar")
   |    |    |
   |    |    | MenuItem - 'System'    (L696, T526, R718, B548)
   |    |    | [u'System2', u'MenuItem', u'SystemMenuItem']
   |    |    | child_window(title="System", control_type="MenuItem")
   |    |
   |    | Button - 'Close'    (L1024, T519, R1058, B549)
   |    | [u'CloseButton', u'Close', 'Button5']
   |    | child_window(title="Close", control_type="Button")

Look at the examples

包括以下示例:注意:示例取决于语言 - 它们仅适用于为其编程的产品语言。 除非突出显示,否则所有示例都已编程为英语软件。

  • mspaint.py Control MSPaint
  • notepad_fast.py使用快速计时设置来控制记事本
  • notepad_slow.py使用慢速计时设置来控制记事本
  • notepad_item.py Use item rather then attribute access to control Notepad.
  • misc_examples.py Show some exceptions and how to get control identifiers.
  • save_from_internet_explorer.py Save a Web Page from Internet Explorer.
  • save_from_firefox.py Save a Web Page from Firefox.
  • get_winrar_info.py Example of how to do multilingual automation. This is not an ideal example (works on French, Czech and German WinRar)
  • forte_agent_sample.py Example of dealing with a complex application that is quite dynamic and gives different dialogs often when starting.
  • windowmediaplayer.py Just another example - deals with check boxes in a ListView.
  • test_sakura.py, test_sakura2.py Two examples of automating a Japanase product.

Automate notepad at the command line

Please find below a sample run

      C:\>python
      Python 2.4.2 (#67, Sep 28 2005, 12:41:11) [MSC v.1310 32 bit (Intel)] on win32
      Type "help", "copyright", "credits" or "license" for more information.
(1)   >>> from pywinauto import application
(2)   >>> app = application.Application()
(3)   >>> app.start("Notepad.exe")
      <pywinauto.application.Application object at 0x00AE0990>
(4)   >>> app.UntitledNotepad.draw_outline()
(5)   >>> app.UntitledNotepad.menu_select("Edit -> Replace")
(6)   >>> app.Replace.print_control_identifiers()
        Control Identifiers:

        Dialog - 'Replace'    (L179, T174, R657, B409)
        ['ReplaceDialog', 'Dialog', 'Replace']
        child_window(title="Replace", class_name="#32770")
           |
           | Static - 'Fi&nd what:'    (L196, T230, R292, B246)
           | ['Fi&nd what:Static', 'Fi&nd what:', 'Static', 'Static0', 'Static1']
           | child_window(title="Fi&nd what:", class_name="Static")
           |
           | Edit - ''    (L296, T226, R524, B250)
           | ['Fi&nd what:Edit', 'Edit', 'Edit0', 'Edit1']
           | child_window(class_name="Edit")
           |
           | Static - 'Re&place with:'    (L196, T264, R292, B280)
           | ['Re&place with:', 'Re&place with:Static', 'Static2']
           | child_window(title="Re&place with:", class_name="Static")
           |
           | Edit - ''    (L296, T260, R524, B284)
           | ['Edit2', 'Re&place with:Edit']
           | child_window(class_name="Edit")
           |
           | CheckBox - 'Match &whole word only'    (L198, T304, R406, B328)
           | ['CheckBox', 'Match &whole word onlyCheckBox', 'Match &whole word only', 'CheckBox0', 'CheckBox1']
           | child_window(title="Match &whole word only", class_name="Button")
           |
           | CheckBox - 'Match &case'    (L198, T336, R316, B360)
           | ['CheckBox2', 'Match &case', 'Match &caseCheckBox']
           | child_window(title="Match &case", class_name="Button")
           |
           | Button - '&Find Next'    (L536, T220, R636, B248)
           | ['&Find Next', '&Find NextButton', 'Button', 'Button0', 'Button1']
           | child_window(title="&Find Next", class_name="Button")
           |
           | Button - '&Replace'    (L536, T254, R636, B282)
           | ['&ReplaceButton', '&Replace', 'Button2']
           | child_window(title="&Replace", class_name="Button")
           |
           | Button - 'Replace &All'    (L536, T288, R636, B316)
           | ['Replace &AllButton', 'Replace &All', 'Button3']
           | child_window(title="Replace &All", class_name="Button")
           |
           | Button - 'Cancel'    (L536, T322, R636, B350)
           | ['CancelButton', 'Cancel', 'Button4']
           | child_window(title="Cancel", class_name="Button")
           |
           | Button - '&Help'    (L536, T362, R636, B390)
           | ['&Help', '&HelpButton', 'Button5']
           | child_window(title="&Help", class_name="Button")
           |
           | Static - ''    (L196, T364, R198, B366)
           | ['ReplaceStatic', 'Static3']
           | child_window(class_name="Static")
(7)   >>> app.Replace.Cancel.click()
(8)   >>> app.UntitledNotepad.Edit.type_keys("Hi from Python interactive prompt %s" % str(dir()), with_spaces = True)
      <pywinauto.controls.win32_controls.EditWrapper object at 0x00DDC2D0>
(9)   >>> app.UntitledNotepad.menu_select("File -> Exit")
(10)  >>> app.Notepad.DontSave.click()
      >>>
  1. 导入pywinauto.application模块(通常是您需要直接导入的唯一模块)

  2. 创建一个Application实例。 对该应用程序的所有访问都是通过该对象完成的。

  3. 我们在步骤2中创建了一个Application实例,但是我们没有提供它所引用的Windows应用程序的任何信息。 通过使用start()方法,我们执行该应用程序并将其连接到Application实例应用程序。

  4. 在记事本对话框周围绘制一个绿色矩形 - 这样我们就知道我们有正确的窗口。

  5. 从应用程序所连接的应用程序的“记事本”对话框的“编辑”菜单中选择“替换”项。 此操作将显示“替换”对话框。

  6. 在“替换”对话框上打印控件的标识符,例如,“替换”对话框中的第一个编辑控件可以通过以下任何标识符引用:

    app.Replace.Edit
    app.Replace.Edit0
    app.Replace.Edit1
    app.FindwhatEdit
    

    最后一个是让用户在阅读脚本后最好了解脚本的功能。

  7. 关闭“替换”对话框。 (在脚本文件中,使用close_click()而不是click()更安全,因为close_click()会等待一段时间以给窗口时间关闭对话框。)

  8. 让我们在记事本文本区域中键入一些文本。 如果没有with_spaces参数,则不会输入空格。 请参阅SendKeys的文档,了解此方法,因为它是SendKeys的一个薄包装器。

  9. 要求退出记事本

  10. 我们将被询问是否要保存 - 单击“否”按钮。

How To’s

How to specify a usable Application instance

Application()实例是与您自动化的应用程序的所有工作的联系点。 因此,Application实例需要连接到进程。 有两种方法可以做到这一点:

start(self, cmd_line, timeout=app_start_timeout)  # instance method:

or:

connect(self, **kwargs)  # instance method:

start()在应用程序未运行时使用,您需要启动它。 以下列方式使用它:

app = Application().start(r"c:\path\to\your\application -a -n -y --arguments")

timeout参数是可选的,只有在应用程序需要很长时间才能启动时才需要使用它。

当需要自动化的程序已经启动时,使用connect() 要指定已在运行的应用程序,您需要指定以下之一:

process:

应用程序的进程ID,例如

app = Application().connect(process=2341)
handle:

应用程序窗口的窗口句柄,例如,

app = Application().connect(handle=0x010f0c)
path:

进程的可执行文件的路径(GetModuleFileNameEx用于查找每个进程的路径并与传入的值进行比较),例如:

app = Application().connect(path=r"c:\windows\system32\notepad.exe")

或者指定窗口的参数的任意组合,这些参数将传递给pywinauto.findwindows.find_elements()函数。 e.g.

app = Application().connect(title_re=".*Notepad", class_name="Notepad")

注意:在使用connect *()之前,应用程序必须准备就绪。 在start()之后找不到应用程序时没有超时或重试。 因此,如果您在pywinauto之外启动应用程序,则需要睡眠或编程等待循环以等待应用程序完全启动。

How to specify a dialog of the application

一旦应用程序实例知道它连接到哪个应用程序,就需要指定要处理的对话框。

有很多不同的方法可以做到这一点。 最常见的是使用项目或属性访问权来根据其标题选择对话框。 e.g

dlg = app.Notepad

or equivalently

dlg = app['Notepad']

下一个最简单的方法是要求top_window(),例如

dlg = app.top_window()

这将返回具有应用程序顶级窗口的最高Z顺序的窗口。

注意:目前这是相当未经测试的,所以我不确定它是否会返回正确的窗口。 它绝对是应用程序的顶级窗口 - 它可能不是Z-Order中最高的窗口。

如果这不是足够的控制,那么你可以使用与传递给findwindows.find_windows()相同的参数,例如

dlg = app.window(title_re="Page Setup", class_name="#32770")

最后,你可以使用最多的控制权

dialogs = app.windows()

这将返回应用程序的所有可见,启用的顶级窗口的列表。 然后,您可以使用handleprops模块中的一些方法选择所需的对话框。 一旦掌握了所需的手柄,就可以使用

app.window(handle=win)

注意:如果对话框的标题很长 - 那么输入的属性访问可能会很长,在这种情况下通常更容易使用

app.window(title_re=".*Part of Title.*")

How to specify a control on a dialog

有许多方法可以指定控件,最简单的方法是

app.dlg.control
app['dlg']['control']

The 2nd is better for non English OS’s where you need to pass unicode strings e.g. app[u'your dlg title'][u'your ctrl title']

该代码根据以下内容为每个控件构建多个标识符:

  • title
  • friendly class
  • title + friendly class

如果控件的标题文本为空(删除非char字符后),则不使用此文本。 相反,我们寻找控件上方和右侧最接近的标题文本。 并附上the friendly class。 So the list becomes

  • friendly class
  • closest text + friendly class

一旦为对话框中的所有控件创建了一组标识符,我们就消除它们的歧义。

use the WindowSpecification.print_control_identifiers() method

e.g.
app.YourDialog.print_control_identifiers()
Sample output
Button - Paper   (L1075, T394, R1411, B485)
        'PaperGroupBox' 'Paper' 'GroupBox'
Static - Si&ze:   (L1087, T420, R1141, B433)
        'SizeStatic' 'Static' 'Size'
ComboBox -    (L1159, T418, R1399, B439)
        'ComboBox' 'SizeComboBox'
Static - &Source:   (L1087, T454, R1141, B467)
        'Source' 'Static' 'SourceStatic'
ComboBox -    (L1159, T449, R1399, B470)
        'ComboBox' 'SourceComboBox'
Button - Orientation   (L1075, T493, R1171, B584)
        'GroupBox' 'Orientation' 'OrientationGroupBox'
Button - P&ortrait   (L1087, T514, R1165, B534)
        'Portrait' 'RadioButton' 'PortraitRadioButton'
Button - L&andscape   (L1087, T548, R1165, B568)
        'RadioButton' 'LandscapeRadioButton' 'Landscape'
Button - Margins (inches)   (L1183, T493, R1411, B584)
        'Marginsinches' 'MarginsinchesGroupBox' 'GroupBox'
Static - &Left:   (L1195, T519, R1243, B532)
        'LeftStatic' 'Static' 'Left'
Edit -    (L1243, T514, R1285, B534)
        'Edit' 'LeftEdit'
Static - &Right:   (L1309, T519, R1357, B532)
        'Right' 'Static' 'RightStatic'
Edit -    (L1357, T514, R1399, B534)
        'Edit' 'RightEdit'
Static - &Top:   (L1195, T550, R1243, B563)
        'Top' 'Static' 'TopStatic'
Edit -    (L1243, T548, R1285, B568)
        'Edit' 'TopEdit'
Static - &Bottom:   (L1309, T550, R1357, B563)
        'BottomStatic' 'Static' 'Bottom'
Edit -    (L1357, T548, R1399, B568)
        'Edit' 'BottomEdit'
Static - &Header:   (L1075, T600, R1119, B613)
        'Header' 'Static' 'HeaderStatic'
Edit -    (L1147, T599, R1408, B619)
        'Edit' 'TopEdit'
Static - &Footer:   (L1075, T631, R1119, B644)
        'FooterStatic' 'Static' 'Footer'
Edit -    (L1147, T630, R1408, B650)
        'Edit' 'FooterEdit'
Button - OK   (L1348, T664, R1423, B687)
        'Button' 'OK' 'OKButton'
Button - Cancel   (L1429, T664, R1504, B687)
        'Cancel' 'Button' 'CancelButton'
Button - &Printer...   (L1510, T664, R1585, B687)
        'Button' 'Printer' 'PrinterButton'
Button - Preview   (L1423, T394, R1585, B651)
        'Preview' 'GroupBox' 'PreviewGroupBox'
Static -    (L1458, T456, R1549, B586)
        'PreviewStatic' 'Static'
Static -    (L1549, T464, R1557, B594)
        'PreviewStatic' 'Static'
Static -    (L1466, T586, R1557, B594)
        'Static' 'BottomStatic'

此示例取自test_application.py

注意此方法打印的标识符已经过使标识符唯一的过程。 因此,如果您有两个编辑框,则它们的标识符中都会列出“Edit”。 实际上,虽然第一个可以被称为“Edit”,“Edit0”,“Edit1”和第二个应该被称为“Edit2”

Note You do not have to be exact!. 假设我们从上面的例子中获取一个实例

Button - Margins (inches)   (L1183, T493, R1411, B584)
        'Marginsinches' 'MarginsinchesGroupBox' 'GroupBox'

让我们说你不喜欢这些

  • GroupBox - 太通用了,它可以是任何组合框
  • MarginsinchesMarginsinchesGroupBox - 这些只是看起来不错,省略'inches'部分会更好

Well you CAN! 代码与您对照对话框中所有可用标识符使用的标识符进行最佳匹配。

例如,如果您进入调试器,您可以看到如何使用不同的标识符

(Pdb) print app.PageSetup.Margins.window_text()
Margins (inches)
(Pdb) print app.PageSetup.MarginsGroupBox.window_text()
Margins (inches)

这也将迎合拼写错误。 虽然你仍然需要小心,好像在对话框中有2个类似的标识符,你使用的拼写错误可能与你想到的另一个控件更相似。

如何将pywinauto与英语以外的应用程序语言一起使用

由于Python不支持代码中的unicode标识符,因此您无法使用属性访问来引用控件,因此您必须使用项访问权或对window()进行显式调用。

So instead of writing

app.dialog_ident.control_ident.click()

You would have to write

app['dialog_ident']['control_ident'].click()

或者明确地使用window()

app.window(title_re="NonAsciiCharacters").window(title="MoreNonAsciiCharacters").click()

To see an example of this check examples\misc_examples.py get_info()

如何处理未按预期响应的控件(例如OwnerDraw控件)

某些控件(尤其是Ownerdrawn控件)不会按预期响应事件。 例如,如果您查看任何HLP文件并转到“索引”选项卡(单击“搜索”按钮),您将看到一个列表框。 在此运行Spy或Winspector将向您显示它确实是一个列表框 - 但它是ownerdrawn。 这意味着开发人员告诉Windows他们将覆盖项目的显示方式并自行完成。 在这种情况下,他们已经使它无法检索字符串:-(。

那导致什么问题呢?

app.HelpTopics.ListBox.texts()                # 1
app.HelpTopics.ListBox.select("ItemInList")   # 2
  1. 将返回一个空字符串列表,这一切都意味着pywinauto无法获取列表框中的字符串
  2. 这将因IndexError而失败,因为ListBox的select(string)方法在文本中查找项目以了解它应该选择的项目的索引。

以下解决方法将适用于此控件

app.HelpTopics.ListBox.select(1)

这将选择列表框中的第二项,因为它不是字符串查找,它可以正常工作。

不幸的是,即便这样也无济于事。 开发人员可以使控件不响应Select等标准事件。 在这种情况下,您可以在列表框中选择项目的唯一方法是使用TypeKeys()的键盘模拟。

这允许您向控件发送任何击键。 所以要选择你要使用的第3个项目

app.Helptopics.ListBox1.type_keys("{HOME}{DOWN 2}{ENTER}")
  • {HOME}将确保突出显示第一个项目。
  • {DOWN 2}然后将亮点向下移动两项
  • {ENTER}将选择突出显示的项目

如果您的应用程序广泛使用类似的控件类型,那么您可以通过从ListBox派生新类来更轻松地使用它,这可以使用有关您的特定应用程序的额外知识。 例如,在WinHelp示例中,每次在列表视图中突出显示某个项目时,其文本都会插入到列表上方的Edit控件中,并且您可以从那里获取该项目的文本,例如:

# print the text of the item currently selected in the list box
# (as long as you are not typing into the Edit control!)
print app.HelpTopics.Edit.texts()[1]

如何访问系统托盘(又名SysTray,又名“Notification Area”)

在时钟附近有表示正在运行的应用程序的图标,该区域通常被称为“系统托盘”。 事实上,这个区域有许多不同的windows/controls装置。 包含图标的控件实际上是一个工具栏。 它是一个带有TrayNotifyWnd类的窗口中的Pager控件的子节点,它位于另一个带有Shell_TrayWnd类的窗口中,所有这些窗口都是正在运行的Explorer实例的一部分。 谢天谢地,你不需要记住所有这些:-)。

需要记住的重要一点是,您正在“Explorer.exe”应用程序中查找一个窗口“Shell_TrayWnd”,该窗口具有标题为“通知区域”的工具栏控件。

解决此问题的一种方法是执行以下操作

import pywinauto.application
app = pywinauto.application.Application().connect(path="explorer")
systray_icons = app.ShellTrayWnd.NotificationAreaToolbar

任务栏模块提供对系统托盘的初步访问。

它定义了以下变量:

explorer_app:定义连接到正在运行的资源管理器的Application()对象。 您可能不需要直接使用它。
TaskBar:任务栏的句柄(包含“开始”按钮,QuickLaunch图标,正在运行的任务等的栏)
StartButton:“Start me up”:-)我想你可能知道这是什么!
QuickLaunch:带有快速启动图标的工具栏
SystemTray:包含时钟和系统托盘图标的窗口
Clock:时钟
SystemTrayIcons:
 工具栏代表系统托盘图标
RunningApplications:
 工具栏代表正在运行的应用程序

我还在模块中提供了两个可用于单击系统托盘图标的功能:

ClickSystemTrayIcon(button):
 您可以使用此按钮左键单击系统托盘中的可见图标。 我不得不专门说明可见图标,因为可能有很多看不见的图标显然无法点击。 按钮可以是任何整数。 如果指定3则会找到并单击第3个可见按钮。 (现在几乎没有执行错误检查,但将来很可能会移动/重命名此方法。)
RightClickSystemTrayIcon(button):
 ClickSytemTrayIcon类似,但执行右键单击。

通常,当您单击/右键单击图标时,会出现一个弹出菜单。 此时要记住的是弹出菜单是应用程序的一部分,自动化而不是资源管理器的一部分。

e.g.

# connect to outlook
outlook = Application.connect(path='outlook.exe')

# click on Outlook's icon
taskbar.ClickSystemTrayIcon("Microsoft Outlook")

# Select an item in the popup menu
outlook.PopupMenu.Menu().get_menu_path("Cancel Server Request")[0].click()

等待长时间操作

GUI应用程序行为通常不稳定,您的脚本需要等待,直到出现新窗口或关闭/隐藏现有窗口。 pywinauto可以隐式等待对话框初始化(使用默认超时)。 很少有方法/功能可以帮助您使代码更容易,更可靠。

Application methods

此方法对于允许在另一个线程中进行延迟初始化的多线程接口非常有用,同时GUI响应并且所有控件都已存在且可以使用。 所以等待特定的窗口存在/状态是没用的。 在这种情况下,整个过程的CPU使用率表明任务计算尚未完成。

Example:

app.wait_cpu_usage_lower(threshold=5) # wait until CPU usage is lower than 5%

WindowSpecification方法

这些方法适用于所有控件。

There is an example containing long waits: install script for 7zip 9.20 x64.

WindowSpecification对象不一定与现有窗口/控件相关。 这只是一个描述,即搜索窗口的几个标准。 wait方法(如果没有引发任何异常)可以保证目标控件存在,甚至可见,启用和/或激活。

Functions in timings module

还有一些对任何Python代码都有用的低级方法。

如果每个函数调用都应该具有时序控制,也可以使用装饰器pywinauto.timings.always_wait_until()pywinauto.timings.always_wait_until_passes()

# call ensure_text_changed(ctrl) every 2 sec until it's passed or timeout (4 sec) is expired

@always_wait_until_passes(4, 2)
def ensure_text_changed(ctrl):
    if previous_text == ctrl.window_text():
        raise ValueError('The ctrl text remains the same while change is expected')

识别控件

帮助您找到所需控件的方法。

How To`s

每种不同控制类型可用的方法

Windows有许多控件,按钮,列表等

PopupMenu

(no extra visible methods)

Static

(no extra visible methods)

Credits

(listed in reverse chronological order)

Vasily Ryabov,Valentin Kroupkin,Alexander Rumyantsev - MS UI Automation后端实现

Ivan Magazinnik - mouse/keyboard input emulation on Linux

Maxim Samokhvalov - initial implementation of hooks.py module

Intel Corporation - Vasily Ryabov revived and maintained the project during his work at Intel (pywinauto 0.5.x)

Valentin Kroupkin (airelil) - continuous integration (AppVeyor), many unit tests improvements (pywinauto 0.5.x)

Michael Herrmann - bug fixes, project maintenance (0.4.x)

Raghav - idea with using metaclass for finding wrapper

Daisuke Yamashita - Bugs/suggestions for 2.5 that MenuWrapper.GetProperties() returns a list rather then a dict

Dalius Dobravolskas - Help on the forums and prompted major improvements on the wait* functionality

Jeff Winkler - Early encouragement, creation of screencasts

Stefaan Himpe - Lots of speed and stability improvements early on

Dev Notes

文件布局

# used by just about everything (and considered a block!) win32defines.py win32functions.py win32structures.py

# Find windows and their attributes findwindows.py handleprops.py

# wrap windows, get extra info for particular controls # set the friendly class name controlscommon_controls.py controlscontrolactions.py controlshwndwrapper.py controlswin32_controls.py

# currently depends on the Friendly class name # probably needs to be refactored to make it independent of controls! # maybe move that stuff to _application_? findbestmatch.py # currently depends on controls!

controlactions.py

testsallcontrols.py testsasianhotkey.py testscomboboxdroppedheight.py testscomparetoreffont.py testsleadtrailspaces.py testsmiscvalues.py testsmissalignment.py testsmissingextrastring.py testsoverlapping.py testsrepeatedhotkey.py teststranslation.py teststruncation.py

controlproperties.py

xml_helpers.py

FindDialog.py PyDlgCheckerWrapper.py

application.py test_application.py

Best matching

difflib提供此支持对于菜单,我们很简单地匹配菜单项的文本。 对于控件,故事更复杂,因为我们想要匹配以下内容:

  • Control text if it exists
  • Friendly Class name
  • Control text + Friendly class name (if control text exists)
  • (Possibly) closest static + FriendlyClassName
e.g.
FindWhatCombo, ComboBox1,
or
Text, TextRiadio, RadioButton2
  1. 控件本身知道应该引用什么
  2. 需要消除对话框中所有控件的歧义
  3. 那我们需要匹配

ATTRIBUTE RESOLUTION

Thinking again... app.dlg.control

TWO LEVELS
  • application.member (Python resolves)
    应用程序对象的属性
  • application.dialog
    对话框参考
THREE LEVELS
  • application.member.attr (Python resolves)
    前一个成员的另一个属性
  • application.dialog.member
    对话框对象的成员
  • application.dialog.control
    对话框的控件
FOUR LEVELS (leaving out Python resolved)
  • application.dialog.member.member
  • application.dialog.control.member

DELAYED RESOLUTION FOR SUCCESS Taking the example

app.dlg.control.action()

如果我们省略语法和编程错误,仍然有很多原因导致它失败。

可能找不到dlg可能无法找到控件dlg或控件可能被禁用

可以在错误的对话框中找到对话框和控件(例如在记事本中,您可以使用“确定”按钮调出2个“页面设置”对话框)

一种解决方案就是在尝试找到每个新对话框之前添加一个“睡眠”(以确保它在那里并准备就绪) - 但这将意味着许多不必要的等待。

So the solution I have tried is:
  • 在最近的可能时间执行完整的属性访问解析
  • 如果失败则等待再试一次
  • 在指定的超时失败后引发原始异常。

这意味着在正常情况下,您没有不必要的等待 - 并且在失败的情况下 - 您仍然会收到错误的异常。

还等待尽可能晚地解决问题会阻止路径的早期部分成功的错误 - 但找到错误的项目。

例如,如果在记事本中找到页面设置对话框

# if this runs too quickly it actually finds the current page setup dialog # before the next dialog opens, but that dialog does not have a Properties # button - so an error is raised. # because we re-run the resolution from the start we find the new pagesetup dialog. app.PageSetup.Properties.Click()

WRITING TO DIALOGS

我们需要一种确保对话框处于活动状态而无需访问控件的方法。 e.g.

app.MainWin.MenuSelect("Something That->Loads a Dialog")
app.Dlg._write("dlg.xml")

or a harder problem:

app.PageSetup.Printer.Click()
app.PageSetup._write("pagesetup.xml")

在第二个示例中,很难确定是否显示了正确的页面设置对话框。

唯一确定的方法是检查某些控制(ID,类,文本,等等)是否存在 - 但是不必处理那些是很好的:-(

Another less declarative (more magic?) 是扫描可用的窗口/控件列表,如果它们没有更改,则接受显示正确的窗口/控件。

在测试和使用XML文件时,我们应该使用它们以确保我们有正确的对话框(通过使用类/ ID)

PYWINAUTO TODO’s

  • 确保为所有未记录的方法/函数添加文档字符串

  • 检查测试的覆盖范围并努力增加测试。

  • 添加SendInput单击方法的测试

  • 使用FuzzyDict实现findbestmatch。

  • 找到一种以更好的方式处理应用程序数据的方法。 目前,如果有人甚至添加了对print_control_identifiers()的调用,它将破坏匹配算法!

  • 需要移动检查控件是__init__方法中的所有者拉出/位图控件,还有自己的方法,比如IsNormallyRendered()(为什么?)

  • 举例说明如何使用Tray Window

  • 修复ToolbarWrapper.PressButton()似乎不起作用(发现在IE示例脚本上工作)

  • 也许提供一个选项,以便可以使用以下命令运行脚本:

    pywinauto.exe yourscript.py
    

    这可以通过创建一个导入脚本的Py2exe包装器(并可选地调用特定的函数?)来实现。

    这样pywinauto可以在没有安装python的情况下使用(无论这是一个很大的要求,我不知道,因为自动化语言无论如何都是python!

  • 消息陷阱 - 如何处理不需要的消息框弹出?

    1. Wait for an Exception then handle it there
    2. set a trap waiting for a specific dialog
    3. 在调用窗口规范时,如果我们找不到窗口,那么我们可以快速浏览可用的指定陷阱以查看是否有任何陷阱 - 如果他们这样做我们可以运行相关的操作 - 然后再次尝试我们的原始对话框
  • 处理添加引用控件(因为它们应该是用于查找窗口的控件)

  • 找到一个变量的引用名,例如,在Dialog._write()中我们可以知道调用_write的变量名(我们不必重复XML文件名!)

  • 如果我们在按钮单击控制后删除延迟然后尝试连续关闭两个对话框可能会失败,因为第一个对话框尚未关闭,第二个可能具有相似的标题和相同的关闭按钮,例如PageSetup.OK.Click() ,PageSetup2.OK.Click()。 一个可能的解决方案可能是在应用程序中保留一个窗口缓存,并且没有两个不同的对话框标识符(在这种情况下为PageSetup和PageSetup2)可以具有相同的句柄 - 因此当我们调用PageSetup2时返回PageSetup的句柄会失败(和我们会按惯例等待,直到成功或超时)。

  • 使用以下任何一项进行调查

    • BringWindowToTop:在图像捕获之前可能需要
    • GetTopWindow:捕获后可能重新设置顶部窗口?
    • EnumThreadWindows
    • GetGUIThreadInfo
  • 使用上下文(右键单击)菜单可以轻松使用

  • 进一步支持.NET控件并下载/创建测试.NET应用程序

  • 看看支持Sytem托盘(例如右键单击图标)

  • 提供SystemTray类(可能是单例)

  • 查看单击和文本输入 - 也许使用SendInput

  • 支持Up-Down控件和其他常用控件

  • 找出control.item.action()或control.action(item)是否更好

  • 创建一个Recorder以可视化创建测试

LOW PRIORITY

  • 创建一个类,可以轻松处理单个窗口(例如,没有应用程序)

  • 允许应用程序在不同的线程中启动,因此我们不会锁定

    • 这已经完成了 - 问题是如果某些消息有指针就无法跨进程发送(因此我们需要发送一条同步消息,等待其他进程在返回之前做出响应)
    • 但我想有可能创建一个发送这些消息的线程?
  • 从HwndWrapper中解放代码 - 除了handleprops中提供的内容之外,几乎没有这些添加内容。 这是必需的主要原因是FriendlyClassName。 所以我需要看看是否可以将其转移到其他地方。

    这样做可能会使heirarchy变得相当扁平并减少对各种包的依赖性

  • 需要将菜单项设置为类,而不是Dlg.MenuSelect,我们应该这样做

    dlg.Menu("blah->blah").Select()
    

    or even

    dlg.Menu.Blah.Blah.Select()
    

为此,我们需要更改菜单的检索方式 - 而不是在开始时获取所有菜单项 - 然后我们只需获得所请求的级别。

这也可以实现这样的目标

dlg.Menu.Blah.Blah.IsChecked()  IsEnabled(), etc

CLOSED (in some way or the other)

  • 单击后允许延迟删除。 目前需要这样做的主要原因是因为如果你关闭一个对话框,然后立即尝试对父进行操作,它可能还没有激活 - 所以需要延迟才能使它变为活动状态。 要解决此问题,我们可能需要在对话框上调用操作时添加更多魔法,例如:在ActionDialog的属性访问上执行以下操作:

    • 检查它是否是一个动作
    • 如果未启用,请稍等一下
    • 如果是,那么稍等一下再试一次
    • 重复,直到成功或超时

    需要解决的主要问题是你不希望同时发生这些等待中的两个(所以在1级的函数中等待,而在另一个函数调用的函数中等待另一次 - 因为这意味着那里当嵌套函数的超时达到调用func尝试成功的次数时,将是一个非常长的延迟!)

  • 通过最近的静态(或周围的组框?)添加引用

  • 需要模块化common_controls的方法,因为目前它们太单一了。

  • 完成从IE保存页面的示例

  • 在选择菜单项之前,我无法弄清楚如何可靠地检查菜单项是否已启用的文档。 (Probably FIXED NOW!)

    例如,如果您尝试单击视图,则在Media Player中为示例 理论上应该使用MF_DISABLED和MF_GRAYED - 但我发现这些都没有更新(至少对于Media Player),直到它们被删除。

  • 实现一个opional timing / config模块,以便可以自定义所有时序

Change Log

0.6.5 Handling Privileges, AutomationID for Win32 etc.

30-July-2018

Enhancements:
  • 检查目标应用程序和Python进程的管理员权限。 这允许在窗口消息不起作用时检测案例。
  • 为“win32”后端添加automation_idcontrol_type属性(对WinForms最有用)。 正确的child_window()关键字是auto_idcontrol_type
  • 切换pypiwin32依赖于pywin32再次成为官方。
  • 新生成器iter_children()iter_descendants()
  • 将方法is_checked()添加到“win32”复选框。
Bug Fixes:
  • Method Application().connect(...) works better with timeout argument.
  • Fix .set_focus() for “uia” backend including minimized window case (issue #443).
  • maximize()/minimize() methods can be chained now.
  • Fix passing keyword arguments to a function for decorators @always_wait_until_passes and @always_wait_until.
  • Use correct types conversion for WaitGuiThreadIdle (issue #497).
  • Fix reporting code coverage on Linux.
  • Use .format() for logging BaseWrapper actions (issue #471).
  • Print warning in case binary type is not determined (issue #387).

0.6.4 NULL pointer access fix and enhancements

21-January-2018

Bug Fixes:
  • Final fix for ValueError: NULL COM pointer access.
Enhancements:
  • Multi-threading mode (MTA) for comtypes is enabled by default, if it’s not initialized by another library before importing pywinauto.

  • Method get_value() has been added to EditWrapper in UIA backend.

  • Method scroll() has been added for all UIA controls which have ScrollPattern implemented.

  • Added methods is_minimized/is_maximized/is_normal/get_show_state for UIAWrapper.

  • Added handling in-place controls inside ListView control and (row, column) indexing in a grid-like table mode. Examples:

    auto_detected_ctrl = list_view.get_item(0).inplace_control()
    
    combo = list_view.get_item(1,1).inplace_control("ComboBox")
    combo.select("Item name")
    
    edit = list_view.get_item(3,4).inplace_control("Edit")
    edit.type_keys("some text{ENTER}", set_foreground=False)
    
    dt_picker = list_view.get_item(2,0).inplace_control("DateTimePicker")
    

0.6.3 A lot of improvements and some optimizations

03-July-2017
  • Improved string representation for all wrapper objects. Thanks airelil!
  • Fixed several sporadic crashes for backend="uia".
  • Fixed several bugs in wait/wait_not methods:
    • Method wait('exists') doesn’t work for backend="uia". Thanks maollm!
    • Methods wait/wait_not take ~ default time (5 sec.) instead of customized timeout like 1 sec.
  • depth param can used in a WindowSpecification now. depth=1 means this control, depth=2 means immediate children only and so on (aligned with print_control_identifiers method). Thanks dmitrykazanbaev!
  • Significantly improved sending keys to an inactive window silently. Special thanks for antonlarin! Now 2 methods are available:
    • send_chars is supposed to send character input (this includes {Enter}, {Tab}, {Backspace}) without Alt/Shift/Ctrl modifiers.
    • send_keystrokes is for key input (including key combinations with Alt/Shift/Ctrl modifiers).
  • Method Application().connect(path='your.exe') uses default timeout Timings.app_connect_timeout. It can accept timeout and retry_interval keyword arguments. Thanks daniil-kukushkin!
  • Method print_control_identifiers is more consistent and minimum 2x faster now! Thanks cetygamer!
  • Fixed subclassing Application with your own methods. Thanks efremovd!
  • Param work_dir can be used in Application().start(...). Thanks efremovd!
  • Class Application has been enriched with methods is_process_running() and wait_for_process_exit(). Thanks efremovd!
  • Module timings uses time.clock() for Python 2.x and time.perf_counter() for Python 3.x so that accident system time change can’t affect on your script behavior. Thanks airelil!
  • Added WireShark example. Thanks ViktorRoy94!
  • Now print_control_identifiers() can dump UI elements tree to a file. Thanks sovrasov!
  • Improved logging actions for backend="uia", extended example for MS Paint. Thanks ArtemSkrebkov!
  • Extended CalendarWrapper for backend="win32" with these methods: get_month_delta, set_month_delta and get_month_range. Thanks Nikita-K!
  • Added method legacy_properties() to UIAWrapper. Thanks AsyaPronina!
  • Improved VB6 ListView detection for backend="win32". Thanks KirillMoizik!
  • Fixed 64-bit specific bug in TreeViewWrapper for backend="win32" (argument 4: <type 'exceptions.OverflowError'>: long int too long to convert).

0.6.2 More bug fixes

28-February-2017
  • Several bugs were fixed:
    • Maximized window is always resized (restored) when calling set_focus().
    • AttributeError: type object ‘_CustomLogger’ has no attribute ‘disable’.
    • print_control_identifiers() gets bytes string on Python 3.x.
    • Importing pywinauto causes debug messages to appear twice.
  • Improved click methods behaviour for Win32 ListView and TreeView: ensure_visible() is called inside before the click.
  • Made taskbar.SystemTrayIcons localization friendly.

0.6.1 Bug fixes and optimizations for UI Automation and beyond

08-February-2017
  • win32_hooks module is well tested and more reliable now. See detailed example.

  • Fixed several bugs and crashes here and there.

    • Crash when ctrl.window_text() becomes None at the right moment. Thanks mborus!
    • HwndWrapper.set_focus() fails when used via interpreter. Thanks Matthew Kennerly!
    • Fix LoadLibrary call error on just released Python 2.7.13. Thanks Kirill Moizik!
    • AttributeError: WindowSpecification class has no ‘CPUUsage’ method.
    • comtypes prints a lot of warnings at import pywinauto.
    • Methods is_dialog() and restore() are missed for UIA backend.
    • Method print_control_identifiers() crashes on some applications with Unicode symbols.
    • Installation by python setup.py install may fail if pyWin32 dependency was installed manually.
    • Bug in resolving attributes: ‘UIAWrapper’ object has no attribute ‘Menu’ for dlg = app.Custom.Menu
    • Method send_chars() can now send {ENTER} to some applications. Thanks Max Bolingbroke!
  • Searching UI elements is faster now especially if you use control_type or auto_id in a WindowSpecification. Method Application.kill() is also optimized in many cases.

  • Added an example for Win10 Calculator.

0.6.0 Introduce MS UI Automation support and many more improvements

30-October-2016
  • This big release introduces MS UI Automation (UIA) support:
    • Just start from app = Application(backend='uia').start('your_app.exe').
    • Supported controls: Menu, Button/CheckBox/RadioButton, ComboBox, Edit, Tab control, List (ListView), DataGrid, Tree, Toolbar, Tooltip, Slider.
  • Documentation is built continuously now on ReadTheDocs. See also improved Getting Started Guide.
  • New multi-backend architecture makes implementation of new platforms support easier in the future. The minimal set for new backend includes its name and two classes inherited from element_info.ElementInfo and from pywinauto.base_wrapper.BaseWrapper. New backend must be registered by function pywinauto.backend.register().
  • Code style is much closer to PEP8: i.e. click_input should be used instead of ClickInput.
  • Initial implementation of the hooks module. Keyboard and mouse event handlers can be registered in the system. It was inspired by pyHook, pyhk, pyhooked and similar modules, but re-written from scratch. Thanks for Max Samokhvalov! The fork of the hooks module is used in pyhooked 0.8 by Ethan Smith.
  • A lot of small improvements are not counted here.

0.5.4 Bug fixes and partial MFC Menu Bar support

30-October-2015
  • Fix bugs and inconsistencies:
    • Add where=”check” possible value to the ListViewWrapper.Click/ClickInput` methods.
    • Add CheckByClickInput and UncheckByClickInput methods for a plain check box.
    • Fix crash while waiting for the window start.
  • Add partial MFC Menu Bar support. The menu bar can be interpreted as a toolbar. Items are clickable by index through experimental MenuBarClickInput method of the ToolbarWrapper.
  • Python 3.5 is supported.

0.5.3 Better Unicode support for SetEditText/TypeKeys and menu items

25-September-2015
  • Better backward compatibility with pywinauto 0.4.2:
    • support Unicode symbols in the TypeKeys method again;
    • allow SetEditText/TypeKeys methods to take non-string arguments;
    • fix taking Unicode parameters in SetEditText/TypeKeys.
  • Fix bug in Wait("active"), raise a SyntaxError when waiting for an incorrect state.
  • Re-consider some timings, update docs for the default values etc.
  • Fix several issues with an owner-drawn menu.
  • MenuItem method Click is renamed to ClickInput while Click = Select now.
  • New SetTransparency method can make a window transparent in a specified degree.

0.5.2 Improve ListView, new methods for CPU usage, DPI awareness

07-September-2015

  • New Application methods: CPUUsage returns CPU usage as a percent (float number), WaitCPUUsageLower waits until the connected process’ CPU usage is lower than a specified value (2.5% by default).
  • A new class _listview_item. It is very similar to _treeview_element.
  • Add DPI awareness API support (Win8+). It allows correct work when all fonts are scaled at 125%, 150% etc (globally or per monitor).
  • “Tools overview” section in docs.
  • Fix number of bugs:
    • TreeViewWrapper.Select doesn’t work when the control is not in focus.
    • TabControlWrapper.Select doesn’t work in case of TCS_BUTTONS style set.
    • ListViewWrapper methods Check/UnCheck are fixed.
    • Toolbar button: incorrect access by a tooltip text.
    • Warning “Cannot retrieve text length for handle” uses print() instead of actionlogger.
    • ClientToScreen method doesn’t return a value (modifying mutable argument is not good practice).

0.5.1 Several fixes, more tests

13-July-2015

  • Resolve pip issues
  • Warn user about mismatched Python/application bitness (64-bit Python should be used for 64-bit application and 32-bit Python is for 32-bit app)
  • Add “TCheckBox” class name to ButtonWrapper detection list
  • Fix DebugMessage method
  • Disable logging (actionlogger.py) by default, provide shortcuts: actionlogger.enable() and actionlogger.disable(). For those who are familiar with standard logging module there’s method actionlogger.set_level(level)

0.5.0 64-bit Py2/Py3 compatibility

30-June-2015

  • 64-bit Python and 64-bit apps support (but 32-bit Python is recommended for 32-bit apps)
  • Python 2.x/3.x compatibility
  • Added pyWin32 dependency (silent install by pip for 2.7 and 3.1+)
  • Improvements for Toolbar, TreeView, UpDown and DateTimePicker wrappers
  • Improved best_match algorithm allows names like ToolbarFile
  • Clicks can be performed with pressed Ctrl or Shift
  • Drag-n-drop and scrolling methods (DragMouse, DragMouseInput, MouseWheelInput)
  • Improved menu support: handling OWNERDRAW menu items; access by command_id (like $23453)
  • Resolved issues with py2exe and cx_freeze
  • RemoteMemoryBlock can now detect memory corruption by checking guard signature
  • Upgraded taskbar module
  • sysinfo module for checking 32-bit or 64-bit OS and Python
  • set_foreground flag in TypeKeys method for typing into in-place controls
  • flags create_new_console and wait_for_idle in Application.start method

0.4.0 Various cleanup and bug fixes

03-April-2010

  • Gracefully Handle dir() calls on Application or WindowSpecification objects (which used hang for a while as these classes would search for windows matching __members__, __methods__ and __bases__). The code now checks for any attribute that starts with ‘__’ and ends with ‘__’ and raises AttributeError immediately. Thanks to Sebastian Haase for raising this.
  • Removed the reference to an Application object in WindowSpecification. It was not used in the class and made the class harder to use. WindowSpecification is now more useful as a utility class.
  • Add imports of application.WindowSpecification and application.Application to pywinauto.__init__.py so that these classes can be used more easily (without having to directly import pywinauto.application). Thanks again to Sebastian Haase.
  • Added a function to empty the clipboard (thanks to Tocer on Sourceforge)
  • Use ‘SendMessageTimeout’ to get the text of a window. (SendMessage will hang if the application is not processing messages)
  • Fixed references to PIL.ImageGrab. PIL add’s it’s module directly to the module path, so it should just be referenced by ImageGrab and not PIL.ImageGrab.
  • Use AttachThreadInput + PostMessage rather than SendMessageTimeout to send mouse clicks.
  • Fix how timeout retry times are calculated in timings.WaitUntil() and timings.Wait
  • Fixed some issues with application.Kill_() method, highlighted due to the changes in the HwndWrapper.Close() method.
  • Fix writing images to XML. It was broken with updates to PIL that I had not followed. Changed the method of knowing if it is an image by checking for various attributes.
  • Renamed WindowSpecification.(Ww)indow() to ChildWindow() and added deprecation messages for the other functions.
  • Improved the tests (fixed test failures which were not pywinauto issues)

0.3.9 Experimental! New Sendkeys, and various fixes

27-November-2009

  • Major change this release is that Sendkeys is no longer a requirement! A replacement that supports Unicode is included with pywinauto. (hopefully soon to be released as a standalone module). Please note - this is still quite untested so this release should be treated with some care..
  • Made sure that default for WindowSpecification.Window_() was to look for non top level windows. The defaults in find_windows() had been changed previously and it now needed to be explicitly overridden.
  • Fixed a missing reference to ‘win32defines’ when referencing WAIT_TIMEOUT another typo of false (changed to False)
  • Removed the restriction to only get the active windows for the process, now it will be possible to get the active windows, even if a process is not specified. From http://msdn.microsoft.com/en-us/library/ms633506%28VS.85%29.aspx it gets the active window for the foreground thread.
  • Hopefully improved Delphi TreeView and ListView handling (added window class names as supported window classes to the appropriate classes).
  • Added support for running UI tests with reference controls. (requried for some localization tests)
  • Various PyLint and PEP8 fixes made.

0.3.8 Collecting improvements from last 2 years

10-March-2009

  • Fixed toolbar button pressing - This required for HwndWrapper.NotifyParent() to be updated (to accept a new ID parameter)
  • Fixed a bug wherea listview without a column control would make pywinauto fail to capture the dialog.
  • Converted documenation from Pudge generated to Sphinx Generated
  • Added some baic support for Pager and Progress controls (no tests yet)
  • Added some more VB ‘edit’ window classes
  • Added some more VB ‘listbox’ window classes
  • Added some more VB ‘button’ window classes
  • Ensured that return value from ComboBoxWrapper.SelectedIndices is always a tuple (there was a bug where it would sometimes be a ctypes array)
  • Changed default for finding windows to find disabled windows as well as enabled ones (previous was to find enabled windows only) (note this may impact scripts that relied on the previous setting i.e. in cases where two dialogs have the same title!)
  • Much better handling of InvalidWindowHandle during automation runs. This could be raised when a closing window is still available when the automation was called, but is gone half way through whatever function was called.
  • Made clicking more robust by adding a tiny wait between each SendMessageTimeout in _perform_click().
  • Added attributes can_be_label and has_title to HwndWrapper and subclasses to specify whether a control can act as a label for other controls, and whether the title should be used for identifying the control. If you have created your own HwndWrapper subclasses you may need to override the defaults.
  • Added a control_id parameter to find_windows which allows finding windows based off of their control id’s
  • Added a FriendlyClassName method to MenuItem
  • Split up the functions for button truncation data
  • Commented out code to get a new font if the font could not be recovered
  • Moved code to get the control font from Truncation test to handleprops
  • Added a function to get the string representation of the bug. (need to refactor PrintBugs at some point).
  • Fixed a variable name (from fname -> font_attrib as fname was not a defined variable!)
  • Forced some return values from MissingExtraString test to be Unicode
  • Fixed the MiscValues test (converted to Unicode and removed some extraneous characters)
  • Updated the path for all unittests
  • Made two unit tests sligthly more robust and less dependent on computer/app settings
  • Updated timing settings for unit tests
  • Updated the examples to work in dev environment.

0.3.7 Merge of Wait changes and various bug fixes/improvements

10-April-2007

  • Added Timings.WaitUntil() and Timings.WaitUntilPasses() which handle the various wait until something in the code. Also refactored existing waits to use these two methods.
  • Fixed a major Handle leak in RemoteMemorBlock class (which is used extensively for ‘Common’ controls. I was using OpenHandle to open the process handle, but was not calling CloseHandle() for each corresponding OpenHandle().
  • Added an active_() method to Application class to return the active window of the application.
  • Added an ‘active’ option to WindowSpecification.Wait() and WaitNot().
  • Some cleanup of the clipboard module. GetFormatName() was improved and GetData() made a little more robust.
  • Added an option to findwindows.find_windows() to find only active windows (e.g. active_only = True). Default is False.
  • Fixed a bug in the timings.Timings class - timing values are Now accessed through the class (Timings) and not through the intance (self).
  • Updated ElementTree import in XMLHelpers so that it would work on Python 2.5 (where elementtree is a standard module) as well as other versions where ElementTree is a separate module.
  • Enhanced Item selection for ListViews, TreeViews - it is now possible to pass strings and they will be searched for. More documentation is required though.
  • Greatly enhanced Toolbar button clicking, selection, etc. Though more documentation is required.
  • Added option to ClickInput() to allow mouse wheel movements to be made.
  • menuwrapper.Menu.GetProperties() now returns a dict like all other GetProperties() methods. This dict for now only has one key ‘MenuItems’ which contains the list of menuitems (which had been the previous return value).

0.3.6b Changes not documented in 0.3.6 history

31-July-2006

  • Fixed a bug in how findbestmatch.FindBestMatches was working. It would match against text when it should not!
  • Updated how timings.Timings.Slow() worked, if any time setting was less then .2 after ‘slowing’ then set it to .2

0.3.6 Scrolling and Treview Item Clicking added

28-July-2006

  • Added parameter to _treeview_item.Rectangle() to have an option to get the Text rectangle of the item. And defaulted to this.
  • Added _treeview_item.Click() method to make it easy to click on tree view items.
  • Fixed a bug in TreeView.GetItem() that was expanding items when it shouldn’t.
  • Added HwndWrapper.Scroll() method to allow scrolling. This is a very minimal implementation - and if the scrollbars are implemented as separate controls (rather then a property of a control - this will probably not work for you!). It works for Notepad and Paint - that is all I have tried so far.
  • Added a call to HwndWrapper.SetFocus() in _perform_click_input() so that calls to HwndWrapper.ClickInput() will make sure to click on the correct window.

0.3.5 Moved to Metaclass control wrapping

24-May-2006

  • Moved to a metaclass implementation of control finding. This removes some cyclic importing that had to be worked around and other then metaclass magic makes the code a bit simpler.
  • Some of the sample files would not run - so I updated them so they would (Thanks to Stefaan Himpe for pointing this out)
  • Disabled saving application data (it was still being saved in Application.RecordMatch() even if the rest of the application data code is disabled. This was causing what appeared to be a memory leak where pywinauto would keep grabbing more and more memory (especially for controls that contain a lot of information). Thanks to Frank Martinez for leading me to this).
  • Added ListViewWrapper.GetItemRect() to enable retrieving the rectangle for a particular item in the listview.
  • Removed references to _ctrl() method within pywinauto as it was raising a DeprecationWarning internally even if the user was not using it.

0.3.4 Fixed issue with latest ctypes, speed gains, other changes

25-Apr-2006

  • The latest version of ctypes (0.9.9.6) removed the code generator I was using some generated code in win32functions.py (stdcall). I was not using those functions so I just commented them out.
  • Started the process of renaming methods of the Application and WindowSpecification classes. I will be converting names to UppercaseNames_(). The trailing _ is to disambiguate the method names from potential Window titles.
  • Updated how print_control_identifiers works so that it now always prints the disambiguated control name. (even for single controls)
  • Added __hash__ to HwndWrapper so that controls could be dictionary keys.
  • Caching various information at various points. For example I cache how well two pieces of text match. For short scripts this has little impact - but for larger script it could well have a major impact. Also caching information for controls that cannot change e.g. TopLeveParent, Parent, etc

0.3.3 Added some methods, and fixed some small bugs

19-Apr-2006

  • Added a wait for the control to be active and configurable sleeps after ‘modifying’ actions (e.g. Select, Deselect, etc)
  • Fixed Timings.Slow() and Timings.Fast() - they could in certain circumstances do the opposite! If you had already set a timing slower or faster then they would set it then they would blindly ignore that and set their own times. I added functionality that they will take either the slowest or fastest of the new/current setting rather then blindly setting to the new value.
  • Fixed some hidden bugs with HwndWrapper.CloseClick()
  • Fixed a bug in setup.py that would raise an error when no argument was specified
  • Added an argument to HwndWrapper.SendMessageTimeout so that the wait options could be passed in.
  • Added HwndWrapper.Close(), Maximize(), Minimize(), Restore() and GetShowState().
  • Commented out all deprecated methods (will be removed completely in some future release).
  • Added Application.kill_() method - which closes all windows and kills the application. If the application is asking if you want to save your changes - you will not be able to click yes or no and the application will be killed anyway!.

0.3.2 Fixed setup.py and some typos

31-Mar-2006

  • Fixed the spelling of Stefaan Himpe’s name
  • Fixed setup.py which was working for creating a distribution but not for installing it (again thanks to Stefaan for pointing it out!)

0.3.1 Performance tune-ups

30-Mar-2006

  • Change calculation of distance in findbestmatch.GetNonTextControlName() so that it does not need to square or get the square root to find the real distance - as we only need to compare values - not have the actual distance. (Thanks to Stefaan Himpe)
  • Compiled regular expression patterns before doing the match to avoid compiling the regular expression for window that is being tested (Thanks to Stefaan Himpe)
  • Made it easier to add your own control tests by adding a file extra_tests.py which needs to export a ModifyRegisteredTests() method. Also cleaned up the code a little.
  • Updated notepad_fast.py to make it easier to profile (adde a method)
  • Changed WrapHandle to use a cache for classes it has matched - this is to avoid having to match against all classes constantly.
  • Changed default timeout in SendMessageTimeout to .001 seconds from .4 seconds this results in a significant speedup. Will need to make this value modifiable via the timing module/routine.
  • WaitNot was raising an error if the control was not found - it should have returned (i.e. success - control is not in any particular state because it does not exist!).
  • Added ListViewWrapper.Deselect() per Chistophe Keller’s suggestion. While I was at it I added a check on the item value passed in and added a call to WaitGuiIdle(self) so that the control has a chance to process the message.
  • Changed doc templates and moved dependencies into pywinauto subversion to ensure that all files were availabe at www.openqa.org and that they are not broken when viewed there.
  • Moved all timing information into the timings.Timings class. There are some simple methods for changing the timings.

0.3.0 Added Application data - now useful for localization testing

20-Mar-2006

  • Added automatic Application data collection which can be used when running the same test on a different spoken language version. Support is still preliminary and is expected to change. Please treat as early Alpha.

    If you have a different language version of Windows then you can try this out by running the notepad_fast.py example with the langauge argument e.g.

    examples\notepad_fast.py language
    

    This will load the application data from the supplied file notepad_fast.pkl and use it for finding the right menu items and controls to select.

  • Test implementation to make it easier to start using an application. Previously you needed to write code like

    app = Application().connect_(title = 'Find')
    app.Find.Close.Click()
    app.NotePad.MenuSelect("File->Exit")
    

    1st change was to implement static methods start() and connect(). These methods return a new Application instance so the above code becomes:

    app = Application.connect(title = 'Find')
    app.Find.Close.Click()
    app.NotePad.MenuSelect("File->Exit")
    

    I also wanted to make it easier to start working with a simple application - that may or may not have only one dialog. To make this situation easier I made window_() not throw if the application has not been start()ed or connect()ed first. This leads to simpler code like:

    app = Application()
    app.Find.Close.Click()
    app.NotePad.MenuSelect("File->Exit")
    

    What happens here is that when you execute any of Application.window_(), Application.__getattr__() or Application.__getitem__() when the application hasn’t been connected or started. It looks for the window that best matches your specification and connects the application to that process.

    This is extra functionality - existing connect_() and start_() methods still exist

  • Fixed HwndWrapper.SetFocus() so that it would work even if the window was not in the foreground. (it now makes the window foreground as well as giving it focus). This overcomes a restriction in Windows where you can only change the foreground window if you own the foreground window.

  • Changed some 2.4’isms that an anonymous commenter left on my blog :-) with these changes pywinauto should run on Python 2.3 (though I haven’t done extensive testing).

  • Commented out controls.common_controls.TabControlWrapper.GetTabState() and TabStates() as these did not seem to be returning valid values anyway.

  • Fixed documentation issues were parts of the documentation were not getting generated to the HTML files.

  • Fixed issue where MenuSelect would sometimes not work as expected. Some Menu actions require that the window that owns the menu be active. Added a call to SetFocus() before selecting a menu item to ensure that the window was active.

  • Fixed Bug 1452832 where clipboard was not closed in clipboard.GetData()

  • Added more unit tests now up to 248 from 207

0.2.5 More refactoring, more tests

07-Mar-2006

  • Added wrapper classes for Menus and MenuItems this enabled cleaner interaction with Menu’s. It also gives more functionality - you can now programmatically Click() on menus, and query if a menu item is checked or not.

  • Added application.WindowSpecification.Wait() and WaitNot() methods. These methods allow you to wait for a control to exist, be visible, be enabled, be ready (both enabled and visible!) or to wait for the control to not be in any of these states. WaitReady(), WaitNotEnabled(), WaitNotVisible() now use these methods. I was able to also add the missing methods WaitNotReady(), WaitEnabled(), WaitVisible(), WaitExists(), WaitnotExists(). Please use Wait() and WaitNot() as I have Deprecated these Wait* methods.

  • Slightly modified timeout waits for control resolution so that a timed function more accurately follows the timeout value specified.

  • Added application.Application.start() and connect() static methods. These methods are factory methods in that they will return an initialized Application instance. They work exactly the same as start_() and connect() as they are implemented in terms of those.

    from pywinauto.application import Application notepad = Application.start(“notepad”) same_notepad = Application.connect(path = “notepad”)

  • Updated the examples to follow changes to the code - and to make them a little more robust.

  • Added a new Controls Overview document page which lists all the actions on all controls.

  • Added more unit tests now up to 207 from 134 (added 68 tests)

0.2.1 Small Release number - big changes

17-Feb-2006

  • Quick release to get many changes out there - but this release has been less tested then I would like for a .3 release.

  • Allow access to non text controls using the closest Text control. This closest text control will normally be the static/label associated with the control. For example in Notepad, Format->Font dialog, the 1st combobox can be refered to as “FontComboBox” rather than “ComboBox1”

  • Added a new control wrapper - PopupMenuWrapper for context menu’s You can now work easily with context menu’s e.g.

    app.Notepad.Edit.RightClick()
    # need to use MenuClick rather then MenuSelect
    app.PopupMenu.MenuClick("Select All")
    app.Notepad.Edit.RightClick()
    app.PopupMenu.MenuClick("Copy")
    

    I could think of merging the RightClick() and MenuSelect() into one method ContextMenuSelect() if that makes sense to most people.

  • Added Support for Up-Down controls

  • Not all top level windows now have a FriendlyClassName of “Dialog”. I changed this because it made it hard to get windows of a particular class. For example the main Notepad window has a class name of “Notepad”.

    This was primarily implemented due to work I did getting the System Tray.

  • Renamed StatusBarWrapper.PartWidths() to PartRightEdges() as this is more correct for what it returns.

  • Changed HwndWrapper.Text() and SetText() to WindowText() and SetWindowText() respectively to try and make it clearer that it is the text returned by GetWindowText and not the text that is visible on the control. This change also suggested that EditWrapper.SetText() be changed to SetEditText() (though this is not a hard requirement EditWrapper.SetText() still exists - but may be deprecated.

  • Added ClickInput, DoubleClickInput, RightClickInput, PressMouseInput ReleaseMouseInput to HwndWrapper - these use SendInput rather then WM_LBUTTONDOWN, WM_RBUTTONUP, etc used by Click, DoubleClick etc.

    I also added a MenuClick method that allows you to click on menu items. This means you can now ‘physically’ drop menus down.

  • Some further working with tooltips that need to be cleaned up.

  • Fixed a bug where coordinates passed to any of the Click operations had the X and Y coordinates swapped.

  • Added new MenuItem and Menu classes that are to the most part hidden but you can get a menu item by doing

    app.Notepad.MenuItem("View")
    app.Notepad.MenuItem("View->Status Bar")
    

    MenuItems have various actions so for example you can use MenuItem.IsChecked() to check if the menu item is checked. Among other methods there are Click() and Enabled().

  • Modified the ‘best match’ algorithm for finding controls. It now searches a couple of times, and tries to find the best fit for the text passed to it. The idea here is to make it more “Select what I want - not that other thing that looks a bit like what I want!”. It is possible this change could mean you need to use new identifiers in scripts - but in general very little modification should be necessary.

    There was also a change to the algorithm that looked for the closest text control. It missed some obvious controls in the previous implementation. It also had a bug for controls above the control rather than to the left.

  • Added a new example scripts SaveFromInternetExplorer.py and SaveFromFirefox.py which show automating downloading of a page from either of these browsers.

  • Added yet more unit tests, there are now a total of 134 tests.

0.2.0 Significant refactoring

06-Feb-2006

  • Changed how windows are searched for (from application) This chage should not be a significant change for users

  • Started adding unit tests (and the have already uncovered bugs that been fixed). They also point to areas of missing functionality that will be addded with future updates

  • Changed from property access to Control attributes to function access If your code was accessing properties of controls then this might be a significant change! The main reasons for doing this were due to the inheritability of properties (or lack there-of!) and the additional scafolding that was required to define them all.

  • Updated the DialogWrapper.MenuSelect() method to notify the parent that it needs to initialize the menu’s before it retrieves the items

  • Added functionality to associate ‘non-text’ controls with the ‘text’ control closest to them. This allows controls to be referenced by:

    app.dlg.<Nearby_text><Window_class>
    

    e.g. to reference the “Footer” edit control in the Page Setup dialog you could use:

    app.PageSetup.FooterEdit
    
  • Added a MoveWindow method to HwndWrapper

  • Did some more cleanup (fixing pylint warnings) but still not finished

  • Added some better support for .NET controls (not to be considered final)

0.1.3 Many changes, few visible

15-Jan-2006

  • Wrote doc strings for all modules, classes and functions

  • Ran pychecker and pylint and fixed some errors/warning

  • changed

    _connect, _start, _window, _control, _write
    

    respectively to

    connect_, start_, window_, connect_, write_
    

    If you forget to change _window, _connect and _start then you will probably get the following error.

    TypeError: '_DynamicAttributes' object is not callable
    
  • pywinauto is now a package name - you need to import it or its modules

  • Changes to the code to deal with pywinauto package name

  • Fixed searching for windows if a Parent is passed in

  • Added Index to retrieved MenuItem dictionary

  • Added a check to ensure that a windows Handle is a valid window

  • Refactored some of the methods in common_controls

  • Refactored how FriendlyClassName is discovered (and still not really happy!

0.1.2 Add Readme and rollup various changes

15-Jan-2006

  • Updated Readme (original readme was incorrect)
  • Added clipboard module
  • Fixed DrawOutline part of tests.__init__.print_bugs
  • Added a NotifyParent to HwndWrapper
  • Make sure that HwndWrapper.ref is initialized to None
  • Refactored some methods of ComboBox and ListBox
  • Updated Combo/ListBox selection methods
  • Removed hardcoded paths from test_application.py
  • Added section to save the document as UTF-8 in MinimalNotepadTest
  • Fixed EscapeSpecials and UnEscapeSpecials in XMLHelpers
  • Made sure that overly large bitmaps do not break XML writing

0.1.1 Minor bug fix release

12-Jan-2006

  • Fixed some minor bugs discovered after release

0.1.0 Initial Release

6-Jan-2006

Source code reference

Basic User Input Modules

pywinauto.mouse

跨平台模块,模拟真实用户之类的鼠标事件

pywinauto.mouse.click(button='left', coords=(0, 0))

Click at the specified coordinates

pywinauto.mouse.double_click(button='left', coords=(0, 0))

Double click at the specified coordinates

pywinauto.mouse.move(coords=(0, 0))

Move the mouse

pywinauto.mouse.press(button='left', coords=(0, 0))

Press the mouse button

pywinauto.mouse.release(button='left', coords=(0, 0))

Release the mouse button

pywinauto.mouse.right_click(coords=(0, 0))

Right click at the specified coords

pywinauto.mouse.scroll(coords=(0, 0), wheel_dist=1)

做鼠标滚轮

pywinauto.mouse.wheel_click(coords=(0, 0))

鼠标中键单击指定的坐标

pywinauto.keyboard

键盘输入仿真模块

通过调用SendKeys方法自动键入活动窗口的键。 您可以使用任何Unicode字符(在Windows上)和下面列出的一些特殊键。 该模块也可在Linux上使用。

Available key codes:

{SCROLLLOCK}, {VK_SPACE}, {VK_LSHIFT}, {VK_PAUSE}, {VK_MODECHANGE},
{BACK}, {VK_HOME}, {F23}, {F22}, {F21}, {F20}, {VK_HANGEUL}, {VK_KANJI},
{VK_RIGHT}, {BS}, {HOME}, {VK_F4}, {VK_ACCEPT}, {VK_F18}, {VK_SNAPSHOT},
{VK_PA1}, {VK_NONAME}, {VK_LCONTROL}, {ZOOM}, {VK_ATTN}, {VK_F10}, {VK_F22},
{VK_F23}, {VK_F20}, {VK_F21}, {VK_SCROLL}, {TAB}, {VK_F11}, {VK_END},
{LEFT}, {VK_UP}, {NUMLOCK}, {VK_APPS}, {PGUP}, {VK_F8}, {VK_CONTROL},
{VK_LEFT}, {PRTSC}, {VK_NUMPAD4}, {CAPSLOCK}, {VK_CONVERT}, {VK_PROCESSKEY},
{ENTER}, {VK_SEPARATOR}, {VK_RWIN}, {VK_LMENU}, {VK_NEXT}, {F1}, {F2},
{F3}, {F4}, {F5}, {F6}, {F7}, {F8}, {F9}, {VK_ADD}, {VK_RCONTROL},
{VK_RETURN}, {BREAK}, {VK_NUMPAD9}, {VK_NUMPAD8}, {RWIN}, {VK_KANA},
{PGDN}, {VK_NUMPAD3}, {DEL}, {VK_NUMPAD1}, {VK_NUMPAD0}, {VK_NUMPAD7},
{VK_NUMPAD6}, {VK_NUMPAD5}, {DELETE}, {VK_PRIOR}, {VK_SUBTRACT}, {HELP},
{VK_PRINT}, {VK_BACK}, {CAP}, {VK_RBUTTON}, {VK_RSHIFT}, {VK_LWIN}, {DOWN},
{VK_HELP}, {VK_NONCONVERT}, {BACKSPACE}, {VK_SELECT}, {VK_TAB}, {VK_HANJA},
{VK_NUMPAD2}, {INSERT}, {VK_F9}, {VK_DECIMAL}, {VK_FINAL}, {VK_EXSEL},
{RMENU}, {VK_F3}, {VK_F2}, {VK_F1}, {VK_F7}, {VK_F6}, {VK_F5}, {VK_CRSEL},
{VK_SHIFT}, {VK_EREOF}, {VK_CANCEL}, {VK_DELETE}, {VK_HANGUL}, {VK_MBUTTON},
{VK_NUMLOCK}, {VK_CLEAR}, {END}, {VK_MENU}, {SPACE}, {BKSP}, {VK_INSERT},
{F18}, {F19}, {ESC}, {VK_MULTIPLY}, {F12}, {F13}, {F10}, {F11}, {F16},
{F17}, {F14}, {F15}, {F24}, {RIGHT}, {VK_F24}, {VK_CAPITAL}, {VK_LBUTTON},
{VK_OEM_CLEAR}, {VK_ESCAPE}, {UP}, {VK_DIVIDE}, {INS}, {VK_JUNJA},
{VK_F19}, {VK_EXECUTE}, {VK_PLAY}, {VK_RMENU}, {VK_F13}, {VK_F12}, {LWIN},
{VK_DOWN}, {VK_F17}, {VK_F16}, {VK_F15}, {VK_F14}

Modifiers:

  • '+': {VK_SHIFT}
  • '^': {VK_CONTROL}
  • '%': {VK_MENU} a.k.a. Alt key

Example how to use modifiers:

SendKeys('^a^c') # select all (Ctrl+A) and copy to clipboard (Ctrl+C)
SendKeys('+{INS}') # insert from clipboard (Shift+Ins)
SendKeys('%{F4}') # close an active window with Alt+F4

可以为特殊键指定重复计数。 {ENTER 2}表示按两次Enter键。

Main User Modules

pywinauto.application module

pywinauto.findbestmatch

用于查找列表中字符串最接近匹配的模块

exception pywinauto.findbestmatch.MatchError(items=None, tofind='')

A suitable match could not be found

class pywinauto.findbestmatch.UniqueDict

处理使其键唯一的字典子类

find_best_matches(search_text, clean=False, ignore_case=False)

返回项目中search_text的最佳匹配项

  • search_text要查找的文本
  • clean是否清除字符串中的非文本字符
  • ignore_case比较字符串不区分大小写
pywinauto.findbestmatch.build_unique_dict(controls)

构建消除歧义的控件列表

分离出不同的功能,以便我们可以获得用于打印的控件标识符。

pywinauto.findbestmatch.find_best_control_matches(search_text, controls)

返回与search_text最匹配的控件

这与find_best_match稍有不同,因为它构建了要使用每个控件的信息进行搜索的文本项列表。 因此,例如,有一个OK,按钮,然后以下全部添加到搜索列表:“OK”,“Button”,“OKButton”

但如果有一个ListView(没有可见的'text'),那么它只会添加“ListView”。

pywinauto.findbestmatch.find_best_match(search_text, item_texts, items, limit_ratio=0.5)

返回与search_text最匹配的项目

  • search_text要搜索的文本
  • item_texts要搜索的文本列表
  • items与要搜索的文本列表对应的项目列表(1到1)。
  • limit_ratio文本与最佳匹配的匹配程度。 如果最佳匹配匹配低于此值,那么它不被视为匹配并且引发MatchError(默认值= .5)
pywinauto.findbestmatch.get_control_names(control, allcontrols, textcontrols)

返回此控件的名称列表

pywinauto.findbestmatch.get_non_text_control_name(ctrl, controls, text_ctrls)

通过查找上方和左侧最接近的文本控件返回此控件的名称

pywinauto.findbestmatch.is_above_or_to_left(ref_control, other_ctrl)

如果other_ctrl在ref_control的上方或左侧,则返回true

pywinauto.findwindows

pywinauto.timings

所有pywinauto的计时设置

该模块有一个对象,应该用于所有时序调整
timings.Timings

有几个预定义的设置

timings.Timings.Fast() timings.Timings.Defaults() timings.Timings.Slow()

以下是可以调整的各个时序设置:

  • window_find_timeout (default 5)
  • window_find_retry (default .09)
  • app_start_timeout (default 10)
  • app_start_retry (default .90)
  • app_connect_timeout (default 5.)
  • app_connect_retry (default .1)
  • cpu_usage_interval (default .5)
  • cpu_usage_wait_timeout (default 20)
  • exists_timeout (default .5)
  • exists_retry (default .3)
  • after_click_wait (default .09)
  • after_clickinput_wait (default .09)
  • after_menu_wait (default .1)
  • after_sendkeys_key_wait (default .01)
  • after_button_click_wait (default 0)
  • before_closeclick_wait (default .1)
  • closeclick_retry (default .05)
  • closeclick_dialog_close_wait (default 2)
  • after_closeclick_wait (default .2)
  • after_windowclose_timeout (default 2)
  • after_windowclose_retry (default .5)
  • after_setfocus_wait (default .06)
  • setfocus_timeout (default 2)
  • setfocus_retry (default .1)
  • after_setcursorpos_wait (default .01)
  • sendmessagetimeout_timeout (default .01)
  • after_tabselect_wait (default .05)
  • after_listviewselect_wait (default .01)
  • after_listviewcheck_wait default(.001)
  • listviewitemcontrol_timeout default(1.5)
  • after_treeviewselect_wait default(.1)
  • after_toobarpressbutton_wait default(.01)
  • after_updownchange_wait default(.1)
  • after_movewindow_wait default(0)
  • after_buttoncheck_wait default(0)
  • after_comboboxselect_wait default(.001)
  • after_listboxselect_wait default(0)
  • after_listboxfocuschange_wait default(0)
  • after_editsetedittext_wait default(0)
  • after_editselect_wait default(.02)
  • drag_n_drop_move_mouse_wait default(.1)
  • before_drag_wait default(.2)
  • before_drop_wait default(.1)
  • after_drag_n_drop_wait default(.1)
  • scroll_step_wait default(.1)
class pywinauto.timings.TimeConfig

Central storage and manipulation of timing values

Defaults()

将所有计时设置为默认时间

Fast()

设置快速计时值

目前,这会通过以下方式更改时间:超时= 1秒等待= 0秒重试= .001秒(最小!)

(如果现有时间更快,那么保持现有时间)

Slow()

Set slow timing values

Currently this changes the timing in the following ways: timeouts = default timeouts * 10 waits = default waits * 3 retries = default retries * 3

(if existing times are slower then keep existing times)

exception pywinauto.timings.TimeoutError
pywinauto.timings.always_wait_until(timeout, retry_interval, value=True, op=<built-in function eq>)

每次为装饰函数/方法调用wait_until(...)的Decorator

pywinauto.timings.always_wait_until_passes(timeout, retry_interval, exceptions=<class 'Exception'>)

装饰器每次为装饰的函数/方法调用wait_until_passes(...)

pywinauto.timings.timestamp()

获得精确的时间戳

pywinauto.timings.wait_until(timeout, retry_interval, func, value=True, op=<built-in function eq>, *args, **kwargs)

等到op(function(* args, ** kwargs), value)为True或直到超时到期

  • timeout该功能将尝试该功能多长时间
  • retry_interval重试之间等待的时间
  • func将要执行的功能
  • value要比较的值(默认为True)
  • op比较函数(默认为相等)
  • args调用时传递给func的可选参数
  • kwargs调用时要传递给func的可选关键字参数

返回函数的返回值如果操作超时,则函数的返回值位于引发的异常的“function_value”属性中。

e.g.

try:
    # wait a maximum of 10.5 seconds for the
    # the objects item_count() method to return 10
    # in increments of .5 of a second
    wait_until(10.5, .5, self.item_count, 10)
except TimeoutError as e:
    print("timed out")
pywinauto.timings.wait_until_passes(timeout, retry_interval, func, exceptions=<class 'Exception'>, *args, **kwargs)

Wait until func(*args, **kwargs) does not raise one of the exceptions

  • timeout该功能将尝试该功能多长时间
  • retry_interval重试之间等待的时间
  • func将要执行的功能
  • exceptions要测试的异常列表(默认值:Exception)
  • args调用时传递给func的可选参数
  • kwargs调用时要传递给func的可选关键字参数

返回函数的返回值如果操作超时,则引发的原始异常位于引发的异常的“original_exception”属性中。

e.g.

try:
    # wait a maximum of 10.5 seconds for the
    # window to be found in increments of .5 of a second.
    # P.int a message and re-raise the original exception if never found.
    wait_until_passes(10.5, .5, self.Exists, (ElementNotFoundError))
except TimeoutError as e:
    print("timed out")
    raise e.

具体功能

pywinauto.clipboard

一些剪贴板包装功能 - 稍后将添加更多功能

pywinauto.clipboard.EmptyClipboard()
pywinauto.clipboard.GetClipboardFormats()

获取当前剪贴板中的格式列表

pywinauto.clipboard.GetData(format_id=<MagicMock name='mock.CF_UNICODETEXT' id='140016406400584'>)

以请求的格式从剪贴板返回数据

pywinauto.clipboard.GetFormatName(format_id)

获取格式值的字符串名称

控件参考

pywinauto.base_wrapper

所有后端中所有包装器的基类

class pywinauto.base_wrapper.BaseMeta

Wrapper对象的抽象元类

static find_wrapper(element)

Abstract static method to find an appropriate wrapper

class pywinauto.base_wrapper.BaseWrapper(element_info, active_backend)

元素的抽象包装。

All other wrappers are derived from this.

can_be_label = False
capture_as_image(rect=None)

Return a PIL image of the control.

See PIL documentation to know what you can do with the resulting image.

children(**kwargs)

将此元素的子元素作为列表返回

它返回BaseWrapper(或子类)实例的列表。 如果没有子项,则返回空列表。

class_name()

返回elenemt的类名

click_input(button='left', coords=(None, None), button_down=True, button_up=True, double=False, wheel_dist=0, use_log=True, pressed='', absolute=False, key_down=True, key_up=True)

单击指定的坐标

  • button The mouse button to click. One of ‘left’, ‘right’, ‘middle’ or ‘x’ (Default: ‘left’, ‘move’ is a special case)
  • coords点击的坐标。(默认值:控件的中心)
  • double是否执行双击(默认值:False)
  • wheel_dist移动鼠标滚轮的距离(默认值:0)
NOTES:

这与click方法的不同之处在于它需要控件在屏幕上可见,但执行更逼真的“点击”模拟。

如果用户移动鼠标,此方法也很容易受到影响,因为在click_input完成之前可以轻松地将鼠标从控件上移开。

client_to_screen(client_point)

Maps point from client to screen coordinates

control_count()

返回此控件的子项数

control_id()

返回元素的ID

只有控件具有有效的ID - 对话框通常没有分配ID。

ID通常在窗口中标识控件 - 但是可能存在重复的ID,例如对话框中的标签可能具有重复的ID。

descendants(**kwargs)

以列表的形式返回此元素的后代

它返回BaseWrapper(或子类)实例的列表。 如果没有后代,则返回空列表。

double_click_input(button='left', coords=(None, None))

双击指定的坐标

drag_mouse_input(dst=(0, 0), src=None, button='left', pressed='', absolute=True)

单击src,将其拖放到dst

  • dst是目标包装器对象或仅是坐标。
  • src是源包装器对象或坐标。 如果src为None,则self用作源对象。
  • 按钮是拖动过程中要按住的鼠标按钮。 它可以是“left”,“right”,“middle”或“x”
  • pressed是键盘在拖动过程中按下的键。
  • absolute指定是否对鼠标指针位置使用绝对坐标
draw_outline(colour='green', thickness=2, fill=<MagicMock name='mock.win32defines.BS_NULL' id='140016409767608'>, rect=None)

在窗口周围画一个轮廓。

  • colour可以是整数,也可以是“red”,“green”,“blue”(默认为“绿色”)
  • thickness矩形的线宽(默认为2)
  • fill如何填充矩形(默认BS_NULL)
  • rect要绘制的矩形的坐标(默认为控件的矩形)
element_info

获取ElementInfo对象的只读属性

friendly_class_name()

返回控件的友好类名

在某些情况下,这与控制类不同。 class_name()是控件的实际“Registered”元素类,而friendly_class_name()希望对用户更有意义。

例如,Checkbox实现为按钮 - 因此CheckBox的类是“Button” - 但友好类是“CheckBox”

friendlyclassname = None
get_properties()

将控件的属性作为字典返回。

has_title = True
is_child(parent)

如果此元素是'parent'的子元素,则返回True。

当元素是另一个元素的直接元素时,元素是另一个元素的子元素。 如果父元素是子元素的父元素链,则元素是给定元素的直接后代。

is_dialog()

如果控件是顶级窗口,则返回true

is_enabled()

元素是否启用

检查是否同时启用了拥有此元素的顶级父级(可能是对话框)和元素本身。

如果要等待某个元素被启用(或等待它被禁用),请使用Application.wait('visible')Application.wait_not('visible')

如果要在未启用元素的情况下立即引发异常,则可以使用BaseWrapper.verify_enabled()。 如果窗口既不可见又启用,则会引发BaseWrapper.VerifyReady()。

is_visible()

元素是否可见

Checks that both the top level parent (probably dialog) that owns this element and the element itself are both visible.

If you want to wait for an element to become visible (or wait for it to become hidden) use Application.wait('visible') or Application.wait_not('visible').

If you want to raise an exception immediately if an element is not visible then you can use the BaseWrapper.verify_visible(). BaseWrapper.verify_actionable() raises if the element is not both visible and enabled.

iter_children(**kwargs)

迭代这个元素的子元素

它返回BaseWrapper(或子类)实例的生成器。

iter_descendants(**kwargs)

迭代这个元素的子类

它返回BaseWrapper(或子类)实例的生成器。

move_mouse_input(coords=(0, 0), pressed='', absolute=True)

移动鼠标

parent()

返回此元素的父元素

请注意,控件的父级不一定是对话框或其他主窗口。 例如,组框可以是某些单选按钮的父级。

要获取主(或顶级)窗口,请使用BaseWrapper.top_level_parent()。

press_mouse_input(button='left', coords=(None, None), pressed='', absolute=True, key_down=True, key_up=True)

使用SendInput按下鼠标按钮

process_id()

返回拥有此窗口的进程的ID

rectangle()

返回元素的矩形

矩形()是屏幕上元素的矩形。 坐标从屏幕的左上角给出。

此方法返回RECT结构,该结构具有top,left,right,bottom属性。 并且有方法width()和height()。 有关更多信息,请参阅win32structures.RECT。

release_mouse_input(button='left', coords=(None, None), pressed='', absolute=True, key_down=True, key_up=True)

Release the mouse button

right_click_input(coords=(None, None))

Right click at the specified coords

root()

返回根元素包装器(桌面)

set_focus()

将焦点设置为此元素

texts()

返回此控件的每个项目的文本

它是控件的字符串列表。 经常重写它以从具有多个项的控件中提取所有字符串。

它始终是包含一个或多个字符串的列表:

  • 第一个元素是控件的窗口文本
  • 后续元素包含控件的任何项目的文本(例如,列表框/组合框中的项目,tabcontrol中的选项卡)
top_level_parent()

返回此控件的顶级窗口

TopLevel父级与父级不同,父级是拥有此元素的元素 - 但它可能不是对话框/主窗口。 例如,大多数组合框都有编辑。 ComboBox是Edit控件的父级。

这将始终返回一个有效的窗口元素(如果控件没有顶级父级,则返回控件本身 - 因为它已经是顶级窗口!)

type_keys(keys, pause=None, with_spaces=False, with_tabs=False, with_newlines=False, turn_off_numlock=True, set_foreground=True)

使用keyboard.SendKeys键入元素的键

这使用重写的keyboard python模块,您可以在其中找到有关keys的用途的文档。

verify_actionable()

验证该元素是否可见并已启用

如果未分别启用或可见,则提升ElementNotEnalbed或ElementNotVisible。

verify_enabled()

验证元素是否已启用

首先检查元素的父元素是否已启用(如果没有父元素则跳过),然后检查元素本身是否已启用。

verify_visible()

Verify that the element is visible

Check first if the element’s parent is visible. (skip if no parent), then check if element itself is visible.

wait_for_idle()

后端特定函数等待线程或窗口的空闲状态

was_maximized()

在最小化之前指示窗口是否最大化

wheel_mouse_input(coords=(None, None), wheel_dist=1, pressed='')

Do mouse wheel

window_text()

窗口文本的元素

相当多的控件具有其他可见的文本,例如,编辑控件通常具有window_text的空字符串,但仍然在编辑窗口中显示文本。

windowclasses = []
writable_props

构建要写入的默认属性的列表。

派生类可以覆盖或扩展此列表,具体取决于它们需要多少控制。

exception pywinauto.base_wrapper.ElementNotEnabled

未启用元素时引发

exception pywinauto.base_wrapper.ElementNotVisible

元素不可见时引发

exception pywinauto.base_wrapper.InvalidElement

传递无效元素时引发

pywinauto.base_wrapper.remove_non_alphanumeric_symbols(s)

使文本可用于属性名称

pywinauto.controls.hwndwrapper

pywinauto.controls.menuwrapper

pywinauto.controls.common_controls

pywinauto.controls.win32_controls

pywinauto.controls.uiawrapper

UI自动化元素的基本包装

class pywinauto.controls.uiawrapper.LazyProperty(fget)

Bases: object

A lazy evaluation of an object attribute.

The property should represent immutable data, as it replaces itself. Provided by: http://stackoverflow.com/a/6849299/1260742

class pywinauto.controls.uiawrapper.UIAWrapper(element_info)

Bases: pywinauto.base_wrapper.BaseWrapper

Default wrapper for User Interface Automation (UIA) controls.

All other UIA wrappers are derived from this.

This class wraps a lot of functionality of underlying UIA features for working with windows.

Most of the methods apply to every single element type. For example you can click() on any element.

automation_id()

Return the Automation ID of the control

can_select_multiple()

An interface to CanSelectMultiple of the SelectionProvider pattern

Indicates whether the UI Automation provider allows more than one child element to be selected concurrently.

children_texts()

Get texts of the control’s children

close()

Close the window

Only a control supporting Window pattern should answer. If it doesn’t (menu shadows, tooltips,...), try to send “Esc” key

collapse()

Displays all child nodes, controls, or content of the control

An interface to Collapse method of the ExpandCollapse control pattern.

expand()

Displays all child nodes, controls, or content of the control

An interface to Expand method of the ExpandCollapse control pattern.

friendly_class_name()

Return the friendly class name for the control

This differs from the class of the control in some cases. class_name() is the actual ‘Registered’ window class of the control while friendly_class_name() is hopefully something that will make more sense to the user.

For example Checkboxes are implemented as Buttons - so the class of a CheckBox is “Button” - but the friendly class is “CheckBox”

get_expand_state()

Indicates the state of the control: expanded or collapsed.

An interface to CurrentExpandCollapseState property of the ExpandCollapse control pattern. Values for enumeration as defined in uia_defines module: expand_state_collapsed = 0 expand_state_expanded = 1 expand_state_partially = 2 expand_state_leaf_node = 3

get_selection()

An interface to GetSelection of the SelectionProvider pattern

Retrieves a UI Automation provider for each child element that is selected. Builds a list of UIAElementInfo elements from all retrieved providers.

get_show_state()

Get the show state and Maximized/minimzed/restored state

Returns values as following

window_visual_state_normal = 0 window_visual_state_maximized = 1 window_visual_state_minimized = 2

has_keyboard_focus()

Return True if the element is focused with keyboard

iface_expand_collapse = None
iface_grid = None
iface_grid_item = None
iface_invoke = None
iface_item_container = None
iface_range_value = None
iface_scroll = None
iface_scroll_item = None
iface_selection = None
iface_selection_item = None
iface_table = None
iface_table_item = None
iface_text = None
iface_toggle = None
iface_transform = None
iface_transformV2 = None
iface_value = None
iface_virtualized_item = None
iface_window = None
invoke()

An interface to the Invoke method of the Invoke control pattern

is_active()

Whether the window is active or not

is_collapsed()

Test if the control is collapsed

is_dialog()

Return true if the control is a dialog window (WindowPattern interface is available)

is_expanded()

Test if the control is expanded

is_keyboard_focusable()

Return True if the element can be focused with keyboard

is_maximized()

Indicate whether the window is maximized or not

is_minimized()

Indicate whether the window is minimized or not

is_normal()

Indicate whether the window is normal (i.e. not minimized and not maximized)

is_selected()

Indicate that the item is selected or not.

Only items supporting SelectionItem pattern should answer. Raise NoPatternInterfaceError if the pattern is not supported

Usually applied for controls like: a radio button, a tree view item, a list item.

is_selection_required()

An interface to IsSelectionRequired property of the SelectionProvider pattern.

This property can be dynamic. For example, the initial state of a control might not have any items selected by default, meaning that IsSelectionRequired is FALSE. However, after an item is selected the control must always have at least one item selected.

legacy_properties()

Get the element’s LegacyIAccessible control pattern interface properties

maximize()

Maximize the window

Only controls supporting Window pattern should answer

menu_select(path, exact=False)

Select a menu item specified in the path

The full path syntax is specified in: pywinauto.menuwrapper.Menu.get_menu_path()

There are usually at least two menu bars: “System” and “Application” System menu bar is a standard window menu with items like: ‘Restore’, ‘Move’, ‘Size’, ‘Minimize’, e.t.c. This menu bar usually has a “Title Bar” control as a parent. Application menu bar is often what we look for. In most cases, its parent is the dialog itself so it should be found among the direct children of the dialog. Notice that we don’t use “Application” string as a title criteria because it couldn’t work on applications with a non-english localization. If there is no menu bar has been found we fall back to look up for Menu control. We try to find the control through all descendants of the dialog

minimize()

Minimize the window

Only controls supporting Window pattern should answer

restore()

Restore the window to normal size

Only controls supporting Window pattern should answer

scroll(direction, amount, count=1, retry_interval=0.1)

Ask the control to scroll itself

direction can be any of “up”, “down”, “left”, “right” amount can be only “line” or “page” count (optional) the number of times to scroll retry_interval (optional) interval between scroll actions

select()

Select the item

Only items supporting SelectionItem pattern should answer. Raise NoPatternInterfaceError if the pattern is not supported

Usually applied for controls like: a radio button, a tree view item or a list item.

selected_item_index()

Return the index of a selected item

set_focus()

Set the focus to this element

writable_props

Extend default properties list.

class pywinauto.controls.uiawrapper.UiaMeta(name, bases, attrs)

Bases: pywinauto.base_wrapper.BaseMeta

Metaclass for UiaWrapper objects

static find_wrapper(element)

Find the correct wrapper for this UIA element

pywinauto.controls.uiawrapper.lazy_property

alias of LazyProperty

pywinauto.controls.uia_controls

Wrap various UIA windows controls

class pywinauto.controls.uia_controls.ButtonWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap a UIA-compatible Button, CheckBox or RadioButton control

click()

Click the Button control by using Invoke pattern

get_toggle_state()

Get a toggle state of a check box control.

The toggle state is represented by an integer 0 - unchecked 1 - checked 2 - indeterminate

The following constants are defined in the uia_defines module toggle_state_off = 0 toggle_state_on = 1 toggle_state_inderteminate = 2

is_dialog()

Buttons are never dialogs so return False

toggle()

An interface to Toggle method of the Toggle control pattern.

Control supporting the Toggle pattern cycles through its toggle states in the following order: ToggleState_On, ToggleState_Off and, if supported, ToggleState_Indeterminate

Usually applied for the check box control.

The radio button control does not implement IToggleProvider, because it is not capable of cycling through its valid states. Toggle a state of a check box control. (Use ‘select’ method instead) Notice, a radio button control isn’t supported by UIA. https://msdn.microsoft.com/en-us/library/windows/desktop/ee671290(v=vs.85).aspx

class pywinauto.controls.uia_controls.ComboBoxWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap a UIA CoboBox control

item_count()

Return the number of items in the combobox

The interface is kept mostly for a backward compatibility with the native ComboBox interface

select(item)

Select the ComboBox item

The item can be either a 0 based index of the item to select or it can be the string that you want to select

selected_index()

Return the selected index

selected_text()

Return the selected text or None

Notice, that in case of multi-select it will be only the text from a first selected item

texts()

Return the text of the items in the combobox

class pywinauto.controls.uia_controls.EditWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible Edit control

get_line(line_index)

Return the line specified

get_value()

Return the current value of the element

has_title = False
line_count()

Return how many lines there are in the Edit

line_length(line_index)

Return how many characters there are in the line

select(start=0, end=None)

Set the edit selection of the edit control

selection_indices()

The start and end indices of the current selection

set_edit_text(text, pos_start=None, pos_end=None)

Set the text of the edit control

set_text(text, pos_start=None, pos_end=None)

Set the text of the edit control

set_window_text(text, append=False)

Override set_window_text for edit controls because it should not be used for Edit controls.

Edit Controls should either use set_edit_text() or type_keys() to modify the contents of the edit control.

text_block()

Get the text of the edit control

texts()

Get the text of the edit control

writable_props

Extend default properties list.

class pywinauto.controls.uia_controls.HeaderItemWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible Header Item control

class pywinauto.controls.uia_controls.HeaderWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible Header control

class pywinauto.controls.uia_controls.ListItemWrapper(elem, container=None)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible ListViewItem control

is_checked()

Return True if the ListItem is checked

Only items supporting Toggle pattern should answer. Raise NoPatternInterfaceError if the pattern is not supported

texts()

Return a list of item texts

class pywinauto.controls.uia_controls.ListViewWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible ListView control

cell(row, column)

Return a cell in the ListView control

Only for controls with Grid pattern support

  • row is an index of a row in the list.
  • column is an index of a column in the specified row.

The returned cell can be of different control types. Mostly: TextBlock, ImageControl, EditControl, DataItem or even another layer of data items (Group, DataGrid)

column_count()

Return the number of columns

columns()

Get the information on the columns of the ListView

get_column(col_index)

Get the information for a column of the ListView

get_header_control()

Return Header control associated with the ListView

get_item(row)

Return an item of the ListView control

  • row can be either an index of the row or a string with the text of a cell in the row you want returned.
get_item_rect(item_index)

Return the bounding rectangle of the list view item

The method is kept mostly for a backward compatibility with the native ListViewWrapper interface

get_items()

Return all items of the ListView control

get_selected_count()

Return a number of selected items

The call can be quite expensieve as we retrieve all the selected items in order to count them

item(row)

Return an item of the ListView control

  • row can be either an index of the row or a string with the text of a cell in the row you want returned.
item_count()

A number of items in the ListView

items()

Return all items of the ListView control

texts()

Return a list of item texts

writable_props

Extend default properties list.

class pywinauto.controls.uia_controls.MenuItemWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible MenuItem control

items()

Find all items of the menu item

select()

Apply Select pattern

class pywinauto.controls.uia_controls.MenuWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible MenuBar or Menu control

item_by_index(idx)

Find a menu item specified by the index

item_by_path(path, exact=False)

Find a menu item specified by the path

The full path syntax is specified in: controls.menuwrapper.Menu.get_menu_path()

Note: $ - specifier is not supported

items()

Find all menu items

class pywinauto.controls.uia_controls.SliderWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible Slider control

has_title = False
large_change()

Get a large change of slider’s thumb

This change is achieved by pressing PgUp and PgDown keys when slider’s thumb has keyboard focus.

max_value()

Get the maximum value of the Slider

min_value()

Get the minimum value of the Slider

set_value(value)

Set position of slider’s thumb

small_change()

Get a small change of slider’s thumb

This change is achieved by pressing left and right arrows when slider’s thumb has keyboard focus.

value()

Get a current position of slider’s thumb

class pywinauto.controls.uia_controls.TabControlWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible Tab control

get_selected_tab()

Return an index of a selected tab

select(item)

Select a tab by index or by name

tab_count()

Return a number of tabs

texts()

Tabs texts

class pywinauto.controls.uia_controls.ToolbarWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible ToolBar control

The control’s children usually are: Buttons, SplitButton, MenuItems, ThumbControls, TextControls, Separators, CheckBoxes. Notice that ToolTip controls are children of the top window and not of the toolbar.

button(button_identifier, exact=True)

Return a button by the specified identifier

  • button_identifier can be either an index of a button or a string with the text of the button.
  • exact flag specifies if the exact match for the text look up has to be applied.
button_count()

Return a number of buttons on the ToolBar

check_button(button_identifier, make_checked, exact=True)

Find where the button is and toggle it

  • button_identifier can be either an index of the button or a string with the text on the button.
  • make_checked specifies the required toggled state of the button. If the button is already in the specified state the state isn’t changed.
  • exact flag specifies if the exact match for the text look up has to be applied
texts()

Return texts of the Toolbar

writable_props

Extend default properties list.

class pywinauto.controls.uia_controls.TooltipWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible Tooltip control

class pywinauto.controls.uia_controls.TreeItemWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible TreeItem control

In addition to the provided methods of the wrapper additional inherited methods can be especially helpful: select(), extend(), collapse(), is_extended(), is_collapsed(), click_input(), rectangle() and many others

ensure_visible()

Make sure that the TreeView item is visible

get_child(child_spec, exact=False)

Return the child item of this item

Accepts either a string or an index. If a string is passed then it returns the child item with the best match for the string.

is_checked()

Return True if the TreeItem is checked

Only items supporting Toggle pattern should answer. Raise NoPatternInterfaceError if the pattern is not supported

sub_elements()

Return a list of all visible sub-items of this control

class pywinauto.controls.uia_controls.TreeViewWrapper(elem)

Bases: pywinauto.controls.uiawrapper.UIAWrapper

Wrap an UIA-compatible Tree control

get_item(path, exact=False)

Read a TreeView item

  • path a path to the item to return. This can be one of the following:
    • A string separated by \ characters. The first character must be \. This string is split on the \ characters and each of these is used to find the specific child at each level. The \ represents the root item - so you don’t need to specify the root itself.
    • A list/tuple of strings - The first item should be the root element.
    • A list/tuple of integers - The first item the index which root to select. Indexing always starts from zero: get_item((0, 2, 3))
  • exact a flag to request exact match of strings in the path or apply a fuzzy logic of best_match thus allowing non-exact path specifiers
item_count()

Return a number of items in TreeView

print_items()

Print all items with line indents

roots()

Return root elements of TreeView

writable_props

Extend default properties list.

预先提供的测试

pywinauto.tests.allcontrols

获取所有控件测试

What is checked此测试不进行实际测试,只返回每个控件。

How is it checked在对话框中的所有控件上进行循环,并将每个控件添加到错误列表中

When is a bug reported For each control.

Bug Extra Information There is no extra information associated with this bug type

Is Reference dialog needed No,but if available the reference control will be returned with the localised control.

False positive bug reports Not possible

Test Identifier The identifier for this test/bug is “AllControls”

pywinauto.tests.allcontrols.AllControlsTest(windows)

Returns just one bug for each control

pywinauto.tests.asianhotkey

Asian Hotkey Format Test

What is checked

This test checks whether the format for shortcuts/hotkeys follows the standards for localised Windows applications. This format is {localised text}({uppercase hotkey}) so for example if the English control is “&Help” the localised control for Asian languages should be “LocHelp(H)”

How is it checked

After checking whether this control displays hotkeys it examines the 1st string of the control to make sure that the format is correct. If the reference control is available then it also makes sure that the hotkey character is the same as the reference. Controls with a title of less than 4 characters are ignored. This has been done to avoid false positive bug reports for strings like “&X:”.

When is a bug reported

A bug is reported when a control has a hotkey and it is not in the correct format. Also if the reference control is available a bug will be reported if the hotkey character is not the same as used in the reference

Bug Extra Information

This test produces 2 different types of bug: BugType: “AsianHotkeyFormat” There is no extra information associated with this bug type

BugType: “AsianHotkeyDiffRef”

There is no extra information associated with this bug type

Is Reference dialog needed

The reference dialog is not needed. If it is unavailable then only bugs of type “AsianHotkeyFormat” will be reported, bug of type “AsianHotkeyDiffRef” will not be found.

False positive bug reports

There should be very few false positive bug reports when testing Asian software. If a string is very short (eg “&Y:”) but is padded with spaces then it will get reported.

Test Identifier

The identifier for this test/bug is “AsianHotkeyTests”

pywinauto.tests.asianhotkey.AsianHotkeyTest(windows)

Return the repeated hotkey errors

pywinauto.tests.comboboxdroppedheight

ComboBox dropped height Test

What is checked It is ensured that the height of the list displayed when the combobox is dropped down is not less than the height of the reference.

How is it checked The value for the dropped rectangle can be retrieved from windows. The height of this rectangle is calculated and compared against the reference height.

When is a bug reported If the height of the dropped rectangle for the combobox being checked is less than the height of the reference one then a bug is reported.

Bug Extra Information There is no extra information associated with this bug type

Is Reference dialog needed The reference dialog is necessary for this test.

False positive bug reports No false bugs should be reported. If the font of the localised control has a smaller height than the reference then it is possible that the dropped rectangle could be of a different size.

Test Identifier The identifier for this test/bug is “ComboBoxDroppedHeight”

pywinauto.tests.comboboxdroppedheight.ComboBoxDroppedHeightTest(windows)

Check if each combobox height is the same as the reference

pywinauto.tests.comparetoreffont

Compare against reference font test

What is checked This test checks all the parameters of the font for the control against the font for the reference control. If any value is different then this is reported as a bug. Here is a list of all the possible values that are tested: lfFaceName The name of the font lfHeight The height of the font lfWidth Average width of characters lfEscapement Angle of text lfOrientation Another angle for the text! lfWeight How bold the text is lfItalic If the font is italic lfUnderline If the font is underlined lfStrikeOut If the font is struck out lfCharSet The character set of the font lfOutPrecision The output precision lfClipPrecision The clipping precision lfQuality The output quality lfPitchAndFamily The pitch and family

How is it checked Each property of the font for the control being tested is compared against the equivalent property of the reference control font for equality.

When is a bug reported For each property of the font that is not identical to the reference font a bug is reported. So for example if the Font Face has changed and the text is bold then (at least) 2 bugs will be reported.

Bug Extra Information The bug contains the following extra information Name Description ValueType What value is incorrect (see above), String Ref The reference value converted to a string, String Loc The localised value converted to a string, String

Is Reference dialog needed This test will not run if the reference controls are not available.

False positive bug reports Running this test for Asian languages will result in LOTS and LOTS of false positives, because the font HAS to change for the localised text to display properly.

Test Identifier The identifier for this test/bug is “CompareToRefFont”

pywinauto.tests.comparetoreffont.CompareToRefFontTest(windows)

Compare the font to the font of the reference control

pywinauto.tests.leadtrailspaces

Different Leading and Trailing Spaces Test

What is checked Checks that the same space characters (<space>, <tab>, <enter>, <vertical tab>) are before and after all non space characters in the title of the control when compared to the reference control.

How is it checked Find the 1st non-space character, and the characters of the title up to that are the leading spaces. Find the last non-space character, and the characters of the title after that are the trailing spaces. These are then compared to the lead and trail spaces from the reference control and if they are not exactly the then a bug is reported.

When is a bug reported When either the leading or trailing spaces of the control being tested does not match the equivalent spaces of the reference control exactly.

Bug Extra Information The bug contains the following extra information

  • Lead-Trail Whether this bug report is for the leading or trailing spaces of the control, String

    This will be either:

    • “Leading” bug relating to leading spaces
    • “Trailing” bug relating to trailing spaces
  • Ref The leading or trailings spaces of the reference string (depending on Lead-Trail value), String

  • Loc The leading or trailings spaces of the local string (depending on Lead-Trail value), String

Is Reference dialog needed This test will not run if the reference controls are not available.

False positive bug reports This is usually not a very important test, so if it generates many false positives then we should consider removing it.

Test Identifier The identifier for this test/bug is “LeadTrailSpaces”

pywinauto.tests.leadtrailspaces.GetLeadSpaces(title)

Return the leading spaces of the string

pywinauto.tests.leadtrailspaces.GetTrailSpaces(title)

Return the trailing spaces of the string

pywinauto.tests.leadtrailspaces.LeadTrailSpacesTest(windows)

Return the leading/trailing space bugs for the windows

pywinauto.tests.miscvalues

Miscellaneous Control properties Test

What is checked This checks various values related to a control in windows. The values tested are class_name The class type of the control style The Style of the control (GetWindowLong) exstyle The Extended Style of the control (GetWindowLong) help_id The Help ID of the control (GetWindowLong) control_id The Control ID of the control (GetWindowLong) user_data The User Data of the control (GetWindowLong) Visibility Whether the control is visible or not

How is it checked After retrieving the information for the control we compare it to the same information from the reference control.

When is a bug reported If the information does not match then a bug is reported.

Bug Extra Information The bug contains the following extra information Name Description ValueType What value is incorrect (see above), String Ref The reference value converted to a string, String Loc The localised value converted to a string, String

Is Reference dialog needed This test will not run if the reference controls are not available.

False positive bug reports Some values can change easily without any bug being caused, for example User Data is actually meant for programmers to store information for the control and this can change every time the software is run.

Test Identifier The identifier for this test/bug is “MiscValues”

pywinauto.tests.miscvalues.MiscValuesTest(windows)

Return the bugs from checking miscelaneous values of a control

pywinauto.tests.missalignment

Missalignment Test

What is checked This test checks that if a set of controls were aligned on a particular axis in the reference dialog that they are all aligned on the same axis.

How is it checked A list of all the reference controls that are aligned is created (ie more than one control with the same Top, Left, Bottom or Right coordinates). These controls are then analysed in the localised dialog to make sure that they are all aligned on the same axis.

When is a bug reported A bug is reported when any of the controls that were aligned in the reference dialog are no longer aligned in the localised control.

Bug Extra Information The bug contains the following extra information Name Description AlignmentType This is either LEFT, TOP, RIGHT or BOTTOM. It tells you how the controls were aligned in the reference dialog. String AlignmentRect Gives the smallest rectangle that surrounds ALL the controls concerned in the bug, rectangle

Is Reference dialog needed This test cannot be performed without the reference control. It is required to see which controls should be aligned.

False positive bug reports It is quite possible that this test reports false positives: 1. Where the controls only just happen to be aligned in the reference dialog (by coincidence) 2. Where the control does not have a clear boundary (for example static labels or checkboxes) they may be miss-aligned but it is not noticeable that they are not.

Test Identifier The identifier for this test/bug is “Missalignment”

pywinauto.tests.missalignment.MissalignmentTest(windows)

Run the test on the windows passed in

pywinauto.tests.missingextrastring

Different number of special character sequences Test

What is checked This test checks to make sure that certain special character sequences appear the in the localised if they appear in the reference title strings. These strings usually mean something to the user but the software internally does not care if they exist or not. The list that is currently checked is: “>>”, “>”, “<<”, “<”, ”:”(colon), ”...”, “&&”, “&”, “”

How is it checked For each of the string to check for we make sure that if it appears in the reference that it also appears in the localised title.

When is a bug reported
  • If the reference has one of the text strings but the localised does not a bug is reported.
  • If the localised has one of the text strings but the reference does not a bug is reported.

Bug Extra Information The bug contains the following extra information

MissingOrExtra Whether the characters are missing or extra from the controls being check as compared to the reference, (String with following possible values)

  • “MissingCharacters” The characters are in the reference but not in the localised.
  • “ExtraCharacters” The characters are not in the reference but are in the localised.

MissingOrExtraText What character string is missing or added, String

Is Reference dialog needed This test will not run if the reference controls are not available.

False positive bug reports Currently this test is at a beta stage filtering of the results is probably necessary at the moment.

Test Identifier The identifier for this test/bug is “MissingExtraString”

pywinauto.tests.missingextrastring.MissingExtraStringTest(windows)

Return the errors from running the test

pywinauto.tests.overlapping

Overlapping Test

What is checked The overlapping test checks for controls that occupy the same space as some other control in the dialog.

  • If the reference controls are available check for each pair of controls:
    • If controls are exactly the same size and position in reference then make sure that they are also in the localised.
    • If a reference control is wholly contained in another make sure that the same happens for the controls being tested.
  • If the reference controls are not available only the following check can be done
    • If controls are overlapped in localised report a bug (if reference is available it is used just to say if this overlapping happens in reference also)

How is it checked Various tests are performed on each pair of controls to see if any of the above conditions are met. The most specific tests that can be performed are done 1st so that the bugs reported are as specific as possible. I.e. we report that 2 controls are not exactly overlapped when they should be rather than jut reporting that they are overlapped which contains less information.

When is a bug reported A bug is reported when:

  • controls are overlapped (but not contained wholly, and not exactly overlapped)
  • reference controls are exactly overlapped but they are not in tested dialog
  • one reference control is wholly contained in another but not in tested dialog

Bug Extra Information This test produces 3 different types of bug: BugType: “Overlapping” Name Description OverlappedRect <What this info is>, rectangle

BugType - “NotContainedOverlap” There is no extra information associated with this bug type

BugType - “NotExactOverlap” There is no extra information associated with this bug type

Is Reference dialog needed For checking whether controls should be exactly overlapped and whether they should be wholly contained the reference controls are necessary. If the reference controls are not available then only simple overlapping of controls will be checked.

False positive bug reports If there are controls in the dialog that are not visible or are moved dynamically it may cause bugs to be reported that do not need to be logged. If necessary filter out bugs with hidden controls.

Test Identifier The identifier for this test is “Overlapping”

class pywinauto.tests.overlapping.OptRect
pywinauto.tests.overlapping.OverlappingTest(windows)

Return the repeated hotkey errors

pywinauto.tests.repeatedhotkey

Repeated Hotkeys Test

What is checked This test checks all the controls in a dialog to see if there are controls that use the same hotkey character.

How is it checked A list of all the hotkeys (converted to uppercase) used in the dialog is created. Then this list is examined to see if any hotkeys are used more than once. If any are used more than once a list of all the controls that use this hotkey are compiled to be used in the bug report.

When is a bug reported If more than one control has the same hotkey then a bug is reported.

Bug Extra Information The bug contains the following extra information Name Description RepeatedHotkey This is the hotkey that is repeated between the 2 controls converted to uppercase, String CharsUsedInDialog This is a list of all the hotkeys used in the dialog, String AllCharsInDialog This is a list of all the characters in the dialog for controls that have a hotkeys, String AvailableInControlS A list of the available characters for each control. Any of the characters in this list could be used as the new hotkey without conflicting with any existing hotkey.

Is Reference dialog needed The reference dialog does not need to be available. If it is available then for each bug discovered it is checked to see if it is a problem in the reference dialog. NOTE: Checking the reference dialog is not so exact here! Only when the equivalent controls in the reference dialog all have the hotkeys will it be reported as being in the reference also. I.e. if there are 3 controls with the same hotkey in the Localised software then those same controls in the reference dialog must have the same hotkey for it to be reported as existing in the reference also.

False positive bug reports There should be very few false positives from this test. Sometimes a control only has one or 2 characters eg “X:” and it is impossible to avoid a hotkey clash. Also for Asian languages hotkeys should be the same as the US software so probably this test should be run on those languages.

Test Identifier The identifier for this test/bug is “RepeatedHotkey”

pywinauto.tests.repeatedhotkey.GetHotkey(text)

Return the position and character of the hotkey

pywinauto.tests.repeatedhotkey.ImplementsHotkey(win)

checks whether a control interprets & character to be a hotkey

pywinauto.tests.repeatedhotkey.RepeatedHotkeyTest(windows)

Return the repeated hotkey errors

pywinauto.tests.translation

Translation Test

What is checked This checks for controls which appear not to be translated.

How is it checked It compares the text of the localised and reference controls.

If there are more than string in the control then each item is searched for in the US list of titles (so checking is not order dependent). The indices for the untranslated strings are returned in a comma separated string. Also the untranslated strings themselves are returned (all as one string). These strings are not escaped and are delimited as “string1”,”string2”,...”stringN”.

When is a bug reported

If the text of the localised control is identical to the reference control (in case, spacing i.e. a binary compare) then it will be flagged as untranslated. Otherwise the control is treated as translated.

Note: This is the method to return the least number of bugs. If there are differences in any part of the string (e.g. a path or variable name) but the rest of the string is untranslated then a bug will not be highlighted

Bug Extra Information The bug contains the following extra information Name Description Strings The list of the untranslated strings as explained above StringIndices The list of indices (0 based) that are untranslated. This will usually be 0 but if there are many strings in the control untranslated it will report ALL the strings e.g. 0,2,5,19,23

Is Reference dialog needed The reference dialog is always necessary.

False positive bug reports False positive bugs will be reported in the following cases. - The title of the control stays the same as the US because the translation is the same as the English text(e.g. Name: in German) - The title of the control is not displayed (and not translated). This can sometimes happen if the programmer displays something else on the control after the dialog is created.

Test Identifier The identifier for this test/bug is “Translation”

pywinauto.tests.translation.TranslationTest(windows)

Returns just one bug for each control

pywinauto.tests.truncation

Truncation Test

What is checked Checks for controls where the text does not fit in the space provided by the control.

How is it checked There is a function in windows (DrawText) that allows us to find the size that certain text will need. We use this function with correct fonts and other relevant information for the control to be as accurate as possible.

When is a bug reported When the calculated required size for the text is greater than the size of the space available for displaying the text.

Bug Extra Information The bug contains the following extra information Name Description Strings The list of the truncated strings as explained above StringIndices The list of indices (0 based) that are truncated. This will often just be 0 but if there are many strings in the control untranslated it will report ALL the strings e.g. 0,2,5,19,23

Is Reference dialog needed The reference dialog does not need to be available. If it is available then for each bug discovered it is checked to see if it is a problem in the reference dialog.

False positive bug reports Certain controls do not display the text that is the title of the control, if this is not handled in a standard manner by the software then DLGCheck will report that the string is truncated.

Test Identifier The identifier for this test/bug is “Truncation”

pywinauto.tests.truncation.TruncationTest(windows)

Actually do the test

Backend Internal Implementation modules

pywinauto.backend

后端组件存储(指向平台特定事物的链接)

class pywinauto.backend.BackEnd(name, element_info_class, generic_wrapper_class)

Minimal back-end description (name & 2 required base classes)

class pywinauto.backend.BackendsRegistry

Registry pattern class for the list of available back-ends

element_class

Return element_info.ElementInfo‘s subclass of the active backend

name

Name of the active backend

wrapper_class

BaseWrapper’s subclass of the active backend

pywinauto.backend.activate(name)

按名称设置活动后端

Possible values of name are “win32”, “uia” or other name registered by the register() function.

pywinauto.backend.element_class()

返回element_info.ElementInfo的活动后端的子类

pywinauto.backend.name()

Return name of the active backend

pywinauto.backend.register(name, element_info_class, generic_wrapper_class)

注册一个新的后端

pywinauto.backend.wrapper_class()

返回BaseWrapper的活动后端的子类

pywinauto.element_info

应该处理不同后端元素的类的接口

class pywinauto.element_info.ElementInfo

Abstract wrapper for an element

children(**kwargs)

返回元素的子元素

class_name

返回元素的类名

control_id

返回控件的ID

descendants(**kwargs)

返回元素的后代

dump_window()

将元素转储到一组属性

enabled

Return True if the element is enabled

static filter_with_depth(elements, root, depth)

返回具有相对于根的特定深度级别的过滤元素

framework_id

返回元素的框架

handle

返回元素的句柄

has_depth(root, depth)

如果元素具有相对于根的特定深度级别,则返回True

iter_children(**kwargs)

迭代元素的孩子

iter_descendants(**kwargs)

迭代元素的后代

name

Return the name of the element

parent

Return the parent of the element

process_id

Return the ID of process that controls this element

rectangle

Return rectangle of element

rich_text

返回元素的文本

set_cache_strategy(cached)

为元素的常用属性设置缓存策略

visible

如果元素可见,则返回True

pywinauto.win32_element_info

pywinauto.uia_element_info

Implementation of the class to deal with an UI element (based on UI Automation API)

class pywinauto.uia_element_info.UIAElementInfo(handle_or_elem=None, cache_enable=False)

UI element wrapper for IUIAutomation API

automation_id

Return AutomationId of the element

children(**kwargs)

Return a list of only immediate children of the element

  • kwargs is a criteria to reduce a list by process, class_name, control_type, content_only and/or title.
class_name

Return class name of the element

control_id

Return ControlId of the element if it has a handle

control_type

Return control type of element

descendants(**kwargs)

Return a list of all descendant children of the element

  • kwargs is a criteria to reduce a list by process, class_name, control_type, content_only and/or title.
dump_window()

Dump window to a set of properties

element

Return AutomationElement’s instance

enabled

Check if the element is enabled

framework_id

Return FrameworkId of the element

handle

Return handle of the element

iter_children(**kwargs)

Return a generator of only immediate children of the element

  • kwargs is a criteria to reduce a list by process, class_name, control_type, content_only and/or title.
name

Return name of the element

parent

Return parent of the element

process_id

Return ProcessId of the element

rectangle

Return rectangle of the element

rich_text

Return rich_text of the element

runtime_id

Return Runtime ID (hashable value but may be different from run to run)

set_cache_strategy(cached=None)

Setup a cache strategy for frequently used attributes

visible

Check if the element is visible

pywinauto.uia_element_info.elements_from_uia_array(ptrs, cache_enable=False)

Build a list of UIAElementInfo elements from IUIAutomationElementArray

pywinauto.uia_defines

Common UIA definitions and helper functions

class pywinauto.uia_defines.IUIA

Singleton class to store global COM objects from UIAutomationCore.dll

build_condition(process=None, class_name=None, title=None, control_type=None, content_only=None)

Build UIA filtering conditions

exception pywinauto.uia_defines.NoPatternInterfaceError

There is no such interface for the specified pattern

pywinauto.uia_defines.get_elem_interface(element_info, pattern_name)

A helper to retrieve an element interface by the specified pattern name

TODO: handle a wrong pattern name

pywinauto.hooks

内部模块

pywinauto.controlproperties

Wrap

class pywinauto.controlproperties.ControlProps(*args, **kwargs)

包装控件从文件读取以类似于hwnd控件

HasExStyle(exstyle)
HasStyle(style)
WindowText(*args, **kwargs)
window_text()
class pywinauto.controlproperties.FuncWrapper(value)

允许属性访问的小类返回可调用对象

pywinauto.controlproperties.GetMenuBlocks(ctrls)
pywinauto.controlproperties.MenuBlockAsControls(menuItems, parentage=None)
pywinauto.controlproperties.MenuItemAsControl(menuItem)

使菜单项看起来像测试的控件

pywinauto.controlproperties.SetReferenceControls(controls, refControls)

为传入的控件设置参考控件

This does some minor checking as following:
  • test that there are the same number of reference controls as controls - fails with an exception if there are not
  • test if all the ID’s are the same or not

pywinauto.handleprops

用于从窗口句柄检索属性的函数

这些是以过程方式实现的,以便对概念开销最小的其他模块有用

pywinauto.handleprops.children(handle)

将句柄列表返回给此窗口的子项

pywinauto.handleprops.classname(handle)

Return the class name of the window

pywinauto.handleprops.clientrect(handle)

Return the client rectangle of the control

pywinauto.handleprops.contexthelpid(handle)

返回窗口的上下文帮助ID

pywinauto.handleprops.controlid(handle)

返回控件的ID

pywinauto.handleprops.dumpwindow(handle)

将窗口转储到一组属性

pywinauto.handleprops.exstyle(handle)

返回窗口的扩展样式

pywinauto.handleprops.font(handle)

将字体作为窗口的LOGFONTW返回

pywinauto.handleprops.has_enough_privileges(process_id)

检查目标进程是否具有足够的权限来查询GUI操作

pywinauto.handleprops.has_exstyle(handle, tocheck)

Return True if the control has extended style tocheck

pywinauto.handleprops.has_style(handle, tocheck)

Return True if the control has style tocheck

pywinauto.handleprops.is64bitbinary(filename)

Check if the file is 64-bit binary

pywinauto.handleprops.is64bitprocess(process_id)

Return True if the specified process is a 64-bit process on x64

Return False if it is only a 32-bit process running under Wow64. Always return False for x86.

pywinauto.handleprops.is_toplevel_window(handle)

Return whether the window is a top level window or not

pywinauto.handleprops.isenabled(handle)

Return True if the window is enabled

pywinauto.handleprops.isunicode(handle)

Return True if the window is a Unicode window

pywinauto.handleprops.isvisible(handle)

Return True if the window is visible

pywinauto.handleprops.iswindow(handle)

Return True if the handle is a window

pywinauto.handleprops.parent(handle)

Return the handle of the parent of the window

pywinauto.handleprops.processid(handle)

Return the ID of process that controls this window

pywinauto.handleprops.rectangle(handle)

Return the rectangle of the window

pywinauto.handleprops.style(handle)

Return the style of the window

pywinauto.handleprops.text(handle)

Return the text of the window

pywinauto.handleprops.userdata(handle)

Return the value of any user data associated with the window

pywinauto.xml_helpers

pywinauto.fuzzydict

Match items in a dictionary using fuzzy matching

Implemented for pywinauto.

This class uses difflib to match strings. This class uses a linear search to find the items as it HAS to iterate over every item in the dictionary (otherwise it would not be possible to know which is the ‘best’ match).

If the exact item is in the dictionary (no fuzzy matching needed - then it doesn’t do the linear search and speed should be similar to standard Python dictionaries.

>>> fuzzywuzzy = FuzzyDict({"hello" : "World", "Hiya" : 2, "Here you are" : 3})
>>> fuzzywuzzy['Me again'] = [1,2,3]
>>>
>>> fuzzywuzzy['Hi']
2
>>>
>>>
>>> # next one doesn't match well enough - so a key error is raised
...
>>> fuzzywuzzy['There']
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "pywinauto
uzzydict.py", line 125, in __getitem__
    raise KeyError(
KeyError: "'There'. closest match: 'hello' with ratio 0.400"
>>>
>>> fuzzywuzzy['you are']
3
>>> fuzzywuzzy['again']
[1, 2, 3]
>>>
class pywinauto.fuzzydict.FuzzyDict(items=None, cutoff=0.6)

Provides a dictionary that performs fuzzy lookup

pywinauto.actionlogger

pywinauto.actionlogger.ActionLogger

alias of _StandardLogger

pywinauto.actionlogger.disable()

Disable pywinauto logging actions

pywinauto.actionlogger.enable()

Enable pywinauto logging actions

pywinauto.actionlogger.reset_level()

Reset a logging level to a default

pywinauto.actionlogger.set_level(level)

Set a logging level for the pywinauto logger.

pywinauto.sysinfo

Simple module for checking whether Python and Windows are 32-bit or 64-bit

pywinauto.sysinfo.is_x64_OS()
pywinauto.sysinfo.is_x64_Python()
pywinauto.sysinfo.os_arch()
pywinauto.sysinfo.python_bitness()

pywinauto.remote_memory_block

Module containing wrapper around VirtualAllocEx/VirtualFreeEx Win32 API functions to perform custom marshalling

exception pywinauto.remote_memory_block.AccessDenied

Raised when we cannot allocate memory in the control’s process

class pywinauto.remote_memory_block.RemoteMemoryBlock(ctrl, size=4096)

Class that enables reading and writing memory in a different process

Address()

Return the address of the memory block

CheckGuardSignature()

read guard signature at the end of memory block

CleanUp()

Free Memory and the process handle

Read(data, address=None, size=None)

Read data from the memory block

Write(data, address=None, size=None)

Write data into the memory block

Indices and tables