Windows应用自动化常见问题

本文是Windows技术自动化的常见问题。如果要自动化Qt,可以参考下面的Windows自动化Qt时候的常见问题及使用技巧:


Windows应用自动化常见问题

Q: DateTimePicker控件识别为Custom,应该如何操作?

A: DateTimePicker是一种组合控件,即由多个基本控件组成的,所以它的类型是Custom或是Pane(在Windows 10)下。下面是自动化组合控件的自动化样例,即如何获取它的值和设置它的值:

JavaScript
Python
let datePicker = model.getCustom("dateTimePicker1")
//获取DateTimePicker的值
console.log('value=' + await datePicker.name())
//设置DateTimePicker的值
await datePicker.click(2, 2);
await datePicker.pressKeys('2018-08-18')
datePicker = model.getCustom("dateTimePicker1")
# 获取DateTimePicker的值
print('value=' + datePicker.name())
# 设置DateTimePicker的值
datePicker.click(2, 2)
datePicker.pressKeys('2018-08-18')

获取值就是拿它的name属性,设置值就是点击前部,并pressKeys输入日期。

Q: 如何提高自动化代码的运行效率(提升运行速度)?

A: Windows 自动化的运行效率与计算机指标(如 CPU、内存)有一定关系,但最主要的耗时通常发生在控件定位(识别)阶段。通过减少重复定位和使用更优的层级结构,可以显著提升运行速度。

1. 缓存控件对象,避免重复定位

当你调用控件的方法时(如 win.restore()),底层实际上包含了两个操作:

  • 定位控件:在 UI 树中查找目标控件(这是最耗时的步骤)。
  • 执行动作:定位完成后执行具体的 API 动作。

如果对同一控件执行多次操作,建议先将控件对象赋值给局部变量(缓存),后续操作直接基于该变量执行。

推荐写法(缓存对象):

JavaScript
Python
// 第一次定位 Window 并缓存到变量
let win = model.getWindow("some_window");

// 后续操作基于缓存对象执行,不再重新定位
await win.restore();  // 此时 restore() 只执行动作
await win.maximize();
# 第一次定位 Window 并缓存到变量
win = model.getWindow("some_window")

# 后续操作基于缓存对象执行,不再重新定位
win.restore()  # 此时 restore() 只执行动作
win.maximize()

不推荐写法(重复定位):

JavaScript
Python
await model.getWindow("some_window").restore();  // 第一次定位并执行
await model.getWindow("some_window").maximize(); // 第二次定位并执行,速度慢
model.getWindow("some_window").restore()  # 第一次定位并执行
model.getWindow("some_window").maximize() # 第二次定位并执行,速度慢

2. 使用容器控件缩小搜索范围

如果要操作的一组控件都在某一个容器(如 Pane、Window)下,可以先获取容器对象,再通过该容器获取子控件。这能减少从根节点开始识别的时间。

例如,"userName"、"password" 和 "login" 都在 "pane1" 下:

JavaScript
Python
let pane = model.getPane('pane1');
let userName = await pane.getEdit('userName');
//...operations on userName
let password = await pane.getEdit('password');
//...operations on password
await pane.getButton('login').click();
pane = model.getPane('pane1')
userName = pane.getEdit('userName')
#...operations on userName
password = pane.getEdit('password')
#...operations on password
pane.getButton('login').click()

注意:并不是所有控件都适合长期缓存。例如同一个菜单在关闭并重新打开后,其控件实例可能已变更。应仅在一次界面生命周期内使用局部变量缓存,避免使用全局变量长期保留控件引用。

Q: 我的代码运行时出错,报UnhandledPromiseRejectionWarning: Unhandled promise rejection ...

A: 当执行的API函数是异步时,即它的返回值是Promise,并且调用时没有捕捉异常就会出这个错误信息。为获得具体的错误信息,可以在调用的代码中用try/catch语句包含抛错的代码,同时await这个Promise,这样异常就会被捕捉到,你可以在catch中处理这个错误,例如:

JavaScript
(async function() {
   try {
      await model.getButton('button1').click();
   } catch(err) {
      console.log(err);
   }
}
如果button1对象不存在或识别不到,上述getButton会产生异常,并被捕捉并打印异常信息。

Q: 在使用连接远程桌面运行时,为什么一旦我最小化远程桌面窗口,我的自动化脚本就无法正常工作?

A: 默认情况下,当远程桌面窗口被最小化时,Windows会尝试节省系统资源,可能会限制或暂停对远程计算机的一些操作,例如图形渲染、输入模拟等。因此,一些需要持续进行的操作,如自动化脚本或者其他需要模拟用户输入的程序,可能无法正常运行。

要解决这个问题,您可以修改本地计算机的注册表设置,确保即使在远程桌面窗口被最小化的情况下,所有的操作也能继续进行。以下是具体步骤:

  1. 在您的本地计算机上,打开"运行"对话框,输入regedit并点击确定,打开注册表编辑器。
  2. 在注册表编辑器中,导航至HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client
  3. 在此处创建一个新的DWORD(32位)值,命名为RemoteDesktop_SuppressWhenMinimized
  4. 双击新创建的项,将其值设置为2

完成以上步骤后,您需要关闭当前的远程桌面连接并重新连接,这样更改才能生效。之后,即使远程桌面窗口被最小化,自动化操作也能正常进行。

results matching ""

    No results matching ""