【提要】

  • github地址:https://github.com/pywinauto/pywinauto

  • 文档:http://pywinauto.readthedocs.io


【辅助工具】

  • Inspect,判断后端使用 uia 还是 win32:http://pywinauto.readthedocs.io/en/latest/getting_started.html

  • Spy++,查看句柄信息


【常用函数】

  • 打开进程:Application.start

  • 连接已打开进程:Application.connect

  • 打印已连接的进程 id:

print('pid: %d' % app.process)
print('pid: %d' % window.process_id())
print('pid: %d' % dlg.process_id())
  • 初始化主窗口:Application.window(**kwargs) ,参数同 findwindows.find_elements,查找窗口的函数参数都与此类似

  • 打印窗口的子控件:WindowSpecification.print_control_identifiers,同 WindowSpecification.dump_tree 

  • 查找子控件直接“点类名”即可,例如:

openDlg.ComboBoxEx32.print_control_identifiers(depth=3)
openDlg.ComboBoxEx32.ComboBox.Edit.set_text('xxx')
  • 根据多条件查找子控件:WindowSpecification.child_window,参数同 findwindows.find_elements,查找窗口的函数参数都与此类似

  • 打印控件的类名或文本:BaseWrapper.class_name、BaseWrapper.window_text

  • 等待某种(某几种)状态:WindowSpecification.wait,注意 wait 中状态组合是“”,wait_not 中状态组合是“”。有以下几种状态:

‘exists’ means that the window is a valid handle
‘visible’ means that the window is not hidden
‘enabled’ means that the window is not disabled
‘ready’ means that the window is visible and enabled
‘active’ means that the window is active
  • 发送快捷键:BaseWrapper.type_keys

# 发送 Ctrl + O
mainWindow.type_keys(r'^O')


【实例】

#encoding=utf-8
#author: walker
#date: 2018-04-26
#summary: 以 pywinauto 调用 ABBYY FineReader 12 Professional 将 pdf 另存为 txt
#sys.version:'3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Intel)]'

import os, sys, time, shutil, ctypes
from pywinauto.application import Application

# 转换单个 pdf 为 txt
# 需要保证输出 txt 文件所在目录是存在的,txt 文件不存在
# 外层许捕获异常
def Pdf2Txt(pdfFile, txtFile):
	print('Enter Pdf2Txt ...')
	
	FineReaderPath = r'F:\software\ABBYY FineReader 12\FineReader.exe'
	UsualTimeout = 30 
	
	cmd = r'"%s" "%s"' % (FineReaderPath, pdfFile)
	print('cmd: %s' % cmd)
	app = Application(backend="win32").start(cmd)
	
	mainWindow = app.window(class_name=r'FineReader12MainWindowClass')
	mainWindow.wait("ready", timeout=UsualTimeout)
	
	statButton = mainWindow.child_window(process=app.process, class_name='Button', title_re=r'\d+ OF \d+ PAGES RECOGNIZED')
	
	statButton.wait("exists visible", timeout=UsualTimeout)
	statButton.wait_not("visible", timeout=RecognizeTimeout)		# 具体转换可能要很久
	
	mainWindow.dump_tree(filename='mainWindow2.txt')

	mainWindow.ToolbarSave.wait('enabled', timeout=RecognizeTimeout).click()	# 点击保存按钮
	
	saveDlg = app.window(class_name=r'#32770', title=r'Save document as')
	saveDlg.wait("exists visible", timeout=UsualTimeout)
	saveDlg.dump_tree(filename='saveDlg.txt')
	saveDlg.DUIViewWndClassName.DirectUIHWND.ComboBox2.select('Text (*.txt)')		# 设置保存格式
	saveDlg.DUIViewWndClassName.DirectUIHWND.FloatNotifySink.ComboBox.Edit.set_text(txtFile)	# 设置保存文件名
	
	saveDlg.DUIViewWndClassName.DirectUIHWND.CheckBox.UncheckByClick()		# 取消复选框的选中状态(保存后打开)

	# saveDlg.type_keys(r'%S')		# 保存为 txt(Alt + S)
	saveDlg.child_window(title="保存(&S)", class_name="Button").wait('ready', timeout=RecognizeTimeout).click()		# 点击保存按钮
	print('保存(&S) Button clicked!')

	saveDlg.wait_not("exists", timeout=UsualTimeout)

	cnt = 0
	for _ in range(0, 100):
		time.sleep(0.1)
		cnt += 1
		if os.path.exists(txtFile):
			break
	
	app.kill()

	saveDlg.wait_not("exists", timeout=UsualTimeout)
	mainWindow.wait_not("exists", timeout=20)
	print('not exists mainWindow!')
	print('current time:%f (%s)' % (time.time(), time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())))

	return True


【shawpan CSDN 系列文章】

  • python自动化工具之pywinauto(零)

  • python自动化工具之pywinauto(一)

  • python自动化工具之pywinauto(二)

  • python自动化工具之pywinauto(三)

  • python自动化工具之pywinauto(四)——批量转换exe视频


【FAQ】

Q:导入 from pywinauto.application import Application 报错(IndexError: list index out of range

A:以管理员身份运行或更改 Python 安装目录。(参考:Pywinauto app = Application.start() is not working and giving error)


Q:type_keys 发送快捷键无效

Q:可能是因为窗口未获取焦点,可用 set_keyboard_focus、has_keyboard_focus 结合使用获取焦点。另外可参考:pywinauto typekeys not working。如果确实经常无效,例如别输入法拦截(干扰),建议改为按钮点击更靠谱。


*** walker ***