告别手动点点点!用Python+pywinauto给Windows软件做个‘外挂’:自动填写表单与保存文件

张开发
2026/4/20 19:07:29 15 分钟阅读

分享文章

告别手动点点点!用Python+pywinauto给Windows软件做个‘外挂’:自动填写表单与保存文件
解放双手用Python打造Windows软件自动化神器每天重复填写表单、点击保存按钮的操作是否让你感到厌倦我曾连续三个月每天花两小时手动操作一个老旧ERP系统直到发现pywinauto这个神器。本文将分享如何用Python构建Windows软件的智能助手让程序替你完成那些枯燥的点击工作。1. 环境准备与工具选型工欲善其事必先利其器。在开始自动化之旅前我们需要搭建合适的开发环境。推荐使用Python 3.8版本这个版本在Windows平台具有最佳的兼容性表现。核心工具包对比工具包主要功能适用场景安装命令pywinauto窗口/控件识别与操作标准Windows应用自动化pip install pywinautopyautogui鼠标/键盘模拟、屏幕操作通用型自动化pip install pyautoguipywin32底层Windows API调用高级窗口管理pip install pypiwin32安装时建议使用国内镜像加速pip install pywinauto pyautogui pypiwin32 -i https://pypi.tuna.tsinghua.edu.cn/simple注意pywin32需要通过pypiwin32安装直接安装pywin32可能会导致导入错误实际项目中这三个库往往需要配合使用。我的经验是优先使用pywinauto进行控件操作遇到特殊场景再结合pyautogui的鼠标键盘模拟而pywin32则用于解决一些底层窗口管理问题。2. 初识pywinauto从记事本自动化开始让我们从一个简单的例子入手 - 自动化操作Windows记事本。这个案例虽然基础但包含了自动化操作的核心流程。典型自动化流程启动目标应用程序定位主窗口和控件执行文本输入操作模拟菜单点击处理保存对话框完整示例代码from pywinauto.application import Application import time # 启动记事本 app Application(backendwin32).start(notepad.exe) # 等待程序启动 time.sleep(1) # 获取主窗口 notepad app.UntitledNotepad # 在编辑区输入文本 notepad.Edit.type_keys(Hello, 这是自动输入的内容) # 通过菜单保存文件 notepad.menu_select(文件-另存为) # 处理保存对话框 save_dlg app[另存为] save_dlg.Edit.set_text(automated_note.txt) save_dlg[保存].click() # 处理覆盖确认如果文件已存在 if app[确认另存为].exists(): app[确认另存为][是].click() # 关闭记事本 app.kill()这段代码演示了完整的自动化流程。实际使用时有几个关键点需要注意backend参数选择win32适用于传统Win32应用uia更适合WPF等现代UI框架操作间适当添加延迟time.sleep避免因程序响应慢导致操作失败使用print_control_identifiers()方法可以打印窗口所有控件信息方便调试3. 实战进阶处理复杂控件识别问题现实中的商业软件往往没有记事本这么规范的控件结构。面对复杂的GUI界面我们需要更高级的定位技巧。3.1 控件定位策略当标准定位方法失效时可以尝试以下替代方案层级定位法# 通过父窗口逐层定位子控件 dlg app.window(title订单系统) toolbar dlg.child_window(class_nameToolbarWindow32) save_btn toolbar.child_window(title保存)模糊匹配定位# 使用正则表达式匹配标题 dlg app.window(title_re.*订单.*)坐标定位法最后手段import pyautogui # 获取控件坐标后使用pyautogui点击 pyautogui.click(x100, y200)3.2 处理动态控件对于运行时动态生成的控件常规定位方法可能失效。这时可以使用wait方法等待控件出现dlg.wait(visible, timeout10) # 等待最多10秒通过相对位置定位# 先定位已知控件再找相对位置的控件 known_ctrl dlg[已知控件] target_x known_ctrl.rectangle().right 10 target_y known_ctrl.rectangle().top pyautogui.click(target_x, target_y)使用图像识别pyautogui# 保存按钮截图button.png button_pos pyautogui.locateOnScreen(button.png) if button_pos: pyautogui.click(button_pos)4. 企业级应用实战ERP系统自动化让我们看一个真实的ERP系统自动化案例。假设需要自动完成以下流程登录系统进入订单录入界面填写订单信息提交保存完整实现代码from pywinauto import Application import time class ERPAutomator: def __init__(self, exe_path): self.app Application(backenduia).start(exe_path) time.sleep(5) # 等待系统启动 def login(self, username, password): login_dlg self.app.window(titleERP登录) login_dlg[用户名Edit].set_text(username) login_dlg[密码Edit].set_text(password) login_dlg[登录Button].click() time.sleep(3) def create_order(self, order_info): # 打开订单模块 self.app[主窗口].child_window(title订单管理).click() time.sleep(1) # 点击新建按钮 self.app[订单管理].child_window(title新建).click() time.sleep(2) # 填写订单信息 order_dlg self.app[新建订单] order_dlg[客户名称ComboBox].select(order_info[customer]) order_dlg[产品列表ListView].select(order_info[products]) order_dlg[数量Edit].set_text(str(order_info[quantity])) # 保存订单 order_dlg[保存Button].click() time.sleep(1) # 处理可能的提示框 if self.app[提示].exists(): self.app[提示][确定].click() def close(self): self.app.kill() # 使用示例 if __name__ __main__: automator ERPAutomator(rC:\ERP\erp_client.exe) try: automator.login(admin, password123) order_data { customer: ABC公司, products: [产品A, 产品C], quantity: 50 } automator.create_order(order_data) finally: automator.close()在这个案例中我们封装了一个ERPAutomator类将复杂的操作流程抽象为简单的方法调用。这种模式在实际项目中非常实用特别是当需要频繁执行相同流程时。5. 调试技巧与性能优化即使是最有经验的开发者在编写自动化脚本时也会遇到各种问题。以下是几个实用的调试技巧5.1 常用调试方法控件识别器使用Inspect.exeWindows SDK自带查看控件属性在代码中打印控件信息dlg.print_control_identifiers()操作日志from pywinauto.timings import Timings Timings.after_clickinput_wait 1 # 设置操作后等待时间慢动作模式from pywinauto.actionlogger import ActionLogger ActionLogger().log lambda *args: print(args) # 打印所有操作5.2 性能优化建议合理设置等待时间# 全局设置超时时间 from pywinauto.timings import Timings Timings.window_find_timeout 10 # 控件查找超时设为10秒使用更快的定位方式# 直接访问比child_window快 dlg.Edit # 快 dlg.child_window(class_nameEdit) # 慢避免不必要的截图# 禁用pyautogui的安全暂停 pyautogui.PAUSE 0 # 默认0.1秒批量操作减少界面刷新# 不好的做法每次操作都触发界面刷新 for item in items: listview.select(item) # 更好的做法一次选择所有项 listview.select(items)6. 异常处理与脚本健壮性自动化脚本在无人值守运行时健壮性尤为重要。以下是提高脚本可靠性的关键策略6.1 常见异常处理控件未找到try: dlg[保存Button].click() except pywinauto.ElementNotFoundError: print(保存按钮未找到尝试备用方案) pyautogui.click(x100, y200) # 使用坐标点击操作超时from pywinauto.timings import TimeoutError try: dlg.wait(ready, timeout10) except TimeoutError: print(窗口加载超时)应用程序崩溃if not app.process_exists(): print(应用已崩溃重新启动) app.start(executable_path)6.2 增强健壮性的技巧添加检查点def ensure_window_active(title): for _ in range(3): if app[title].exists(): return True time.sleep(1) return False实现自动恢复def safe_click(ctrl, max_retry3): for attempt in range(max_retry): try: ctrl.click() return True except Exception as e: print(f点击失败重试 {attempt1}/{max_retry}) time.sleep(1) return False日志记录import logging logging.basicConfig( filenameautomation.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s )7. 扩展应用自动化测试框架集成pywinauto不仅可以用于日常办公自动化还能与测试框架集成构建强大的GUI自动化测试解决方案。7.1 与pytest集成import pytest from pywinauto.application import Application pytest.fixture(scopemodule) def app(): application Application().start(notepad.exe) yield application application.kill() def test_notepad_edit(app): notepad app.UntitledNotepad notepad.Edit.type_keys(测试文本) assert 测试文本 in notepad.Erid.get_line(0)7.2 生成测试报告结合Allure框架生成美观的测试报告import allure from pywinauto.keyboard import send_keys allure.step(在记事本中输入文本) def enter_text(window, text): window.Edit.type_keys(text) allure.step(验证文本内容) def verify_text(window, expected): assert expected in window.Edit.get_line(0)7.3 持续集成配置在Jenkins等CI工具中运行GUI自动化测试需要特殊配置确保构建节点有图形界面环境设置虚拟显示器对于无界面服务器# Linux下使用Xvfb Xvfb :1 -screen 0 1024x768x24 export DISPLAY:18. 安全注意事项与最佳实践虽然自动化工具能大幅提高效率但不当使用也可能带来风险。以下是一些重要的安全准则密码安全# 避免在代码中硬编码密码 import keyring password keyring.get_password(erp_system, admin)操作确认def confirm_dangerous_action(): if not pyautogui.confirm(确定要执行此操作吗): raise Exception(用户取消了危险操作)权限最小化使用普通用户账号运行自动化脚本限制脚本的访问权限脚本加密对敏感脚本进行加密使用PyArmor等工具保护代码操作审计def log_action(action, details): with open(audit.log, a) as f: timestamp datetime.now().isoformat() f.write(f{timestamp} - {action} - {details}\n)在实际项目中我建议将自动化脚本视为正式的生产力工具为其建立版本控制、代码审查和备份机制就像对待其他重要代码一样。

更多文章