如何在Azure DevOps流水线中执行需活跃GUI的pywinauto自动化脚本?
问题描述
开发了用于桌面应用自动化的pywinauto脚本,在代理机器手动运行完全正常,但通过Azure DevOps流水线执行时,脚本无法识别应用元素,抛出超时错误:
File "features\steps\launch_app_steps.py", line 16, in step_given_User_is_logged_to_app_with_SSO_login
2024-05-22T06:22:39.8642301Z wait_until(timeout=55, retry_interval=0.7, func=lambda: context.signinWindow.exists())
2024-05-22T06:22:39.8643588Z File "C:\Agent\Python\Lib\site-packages\pywinauto\timings.py", line 375, in wait_until
2024-05-22T06:22:39.8643885Z raise err
2024-05-22T06:22:39.8644165Z pywinauto.timings.TimeoutError: timed out
核心原因是pywinauto依赖可视桌面会话访问应用元素,而流水线默认执行环境通常是无桌面的后台会话,导致元素识别失败。
可行解决方案
1. 将Azure DevOps代理切换为交互式模式
默认代理以服务模式后台运行,无桌面会话,需改为交互式启动:
- 停止代理服务:管理员权限打开命令提示符,执行
net stop vstsagent.{池名称}.{代理名称} - 进入代理安装目录,执行
run.cmd启动代理,保持该命令窗口处于打开状态(可借助工具让其在后台维持会话)
2. 流水线任务配置为在用户上下文运行
- 确保作业指定Windows代理:在流水线YAML中添加
demands: Agent.OS -equals Windows_NT - 执行脚本的PowerShell/Cmd任务,勾选**"Run in user context"**选项(仅自托管代理可见)
- 或用
psexec强制在桌面会话启动脚本:# 先通过query session查看实际会话ID,通常交互式会话为1 query session psexec -i 1 -s python your_script.py
3. 调整pywinauto的应用连接方式
- 启动应用时适配流水线环境:
from pywinauto import Application # 禁用新控制台窗口,避免后台会话无法识别 app = Application(backend="uia").start("your_app.exe", create_new_console=False) - 尝试切换backend(win32/uia),部分应用在不同backend下识别效率不同:
app = Application(backend="win32").connect(title="你的应用窗口标题")
4. 维持代理机器桌面会话激活状态
- 本地组策略配置:路径
计算机配置 -> 管理模板 -> Windows组件 -> 远程桌面服务 -> 远程桌面会话主机 -> 会话时间限制,启用**"不允许断开交互式用户会话"** - 用AutoHotkey脚本防止会话锁定:
#Persistent SetTimer, KeepActive, 60000 KeepActive: Send {F15} ; 发送无干扰按键维持会话激活 return
内容的提问来源于stack exchange,提问作者Nithish Duraikannan

