Windows游戏自动化-01现有技术分析

现有Windows自动化技术

目前Windows应用自动化主要是基于Windows API、MSAA、UIAutomation实现。

Win32 API

测试思路:

(1)测试程序首先通过 FindWindowEx和EnumWindow遍历窗口和子窗口;
(2)通过元素属性找到测试元素(按钮…),然后可以通过API检查测试目标;
(3)通过GetWindowRect读取按钮坐标位置等;
(4)对于用户行为模拟,可以直接通过SendKey API来完成。

缺点

缺点:完全依赖于Windows底层,完全依赖Windows API。如果碰到一个非标准(自定义控件),用这种方式实现的自动化工具基本上完全束手无策,即使有开发团队的支持也很难完成自动化。

MSAA

Microsoft Active Accessibility, Microsoft活动辅助功能

初衷:

UI程序可以暴露出一个Interface,方便另一个程序对其进行控制。
MSAA技术的初衷是为了方便残疾人使用Windows 程序。比如盲人看不到窗口,但是盲人可以通过一个USB读屏器连接到电脑上,读屏器通过UI程序暴露出来的这个Interface,就可以获取程序信息,通过盲文或者其它形式传递给盲人。

测试思路:

(1)测试程序调用Windows API: AccessibleObjectFromWindow,传入目标UI程序HWND;
(2)AccessibleObjectFromWindow函数向UI程序发送WM_GETOBJECT消息;
(3)UI程序创建实现了IAccessible的内部类,然后通过LresultFromObject API把IAccessible 接口返回给测试程序;
(4)测试程序拿到IAccessible接口,开始调用IAccessible接口函数操作测试目标;
(5)通过IAccessible接口的一些函数获取空间树、元素信息等进行自动化。
被测程序需要支持MSAA,实现对应的COM接口,然后测试程序就可以通过MSAA接口读取UI元素。

缺点:

虽然说MSAA基于COM技术, 但IAccessible并不是一个COM标准接口。
比如使用者无法通过QueryInterface进一步获取更多的自定义接口。这局限了MSAA所能提供的功能。
IAccessible接口的定义有缺陷。里面不少方法是可有可无的,但是又缺少一些支持UI自动化的关键方法。 比如它提供了accSelect支持控件的选取,但是却没有类似accExpand这样的方法支持树状控件的展开等。

Microsoft UIAutomation

微软从Windows Vista开始推出的一套全新UI自动化测试技术, 简称UIA。
UIA定义了全新的、针对UI自动化的接口和模式:

  • TreeWalker、FindAll分别支持对UI元素进行遍历和条件化查询;
  • 定义了读写UI元素属性的UIA Property, 包括Name、 ID、Type、ClassName、Location、 Visibility等等;
  • 定义了UI元素行为的UIA Pattern, 比如Select、Expand、Resize、 Check、Value等等。
  • 定义了Control Patterns,比如Button,用InvokePattern来调用它,就可以直接的触发Click的动作(ExpandCollapsePattern, ScrollPattern, TogglePattern…)

UIAutomation不能识别一些程序内的控件或部分不支持,这并不是UIAutomation的问题,是程序作者没有处理WM_GETOBJECT或没有实现UIAutomation Provider,或者故意不想支持UIAutomation。

各种自动化框架对Windows应用支持情况

Win32 MFC WinForms WPF Java AWT/Swing Qt browsers 游戏 Metro APP
Win32 API × × ×
MSAA × × ×
UIA × ×

对于Java桌面程序的自动化了解的不是很深入,查了一下相关技术:

  1. FEST-Swing,一个用于Swing GUI应用程序功能测试的java开源类库。

基于图像的Windows游戏自动化技术

为什么会出现基于图像的自动化技术?

  1. 一些游戏或者一些特殊应用的ui控件比较难以识别
  2. 为了安全,游戏一般没有支持UIAutomation,无法利用UIA等方式进行操作

Sikuli

由 MIT的研究团队发布的新型图形化编程技术。
OpenCV的C++引擎用于在屏幕内搜索制定的图片,java.awt.Robot用来传递键盘和鼠标的事件流

问题

1、sikuli不支持中文,因此无论在编程中或者保存路径,都不可以使用中文!否则运行报错;
2、图片的分辨率、色彩、尺寸、唯一性对程序的影响
3、很多端游

Airtest

网易的一款工具。支持对PC、移动、游戏等多种APP。
Windows自动化部分,鼠标键盘操作部分,主要是使用了开源库pywinauto,而pywinauto支持的就是win 32 api和uia两种,所以airtest对大部分端游是不能进行自动化的。
匹配算法使用的是模板匹配和特征匹配两种(基于sift进行图像识别),哪一个优先匹配上就返回哪一个。
对于手游,网易用的是Poco框架,需要在游戏中加入对应的sdk才能获取游戏内的空间。

为什么现有的技术不能在游戏中使用

  1. 现有的成熟框架中,鼠标键盘操作在很多游戏中失效
    Windows游戏很多使用的是DirectInput,它是DirectX中用于处理用户输入输出的接口,在读取键盘操作时绕过了windows的消息机制。DirectInput API下的软件和游戏,是直接和键盘和鼠标的驱动层交互的。
    原因:有些游戏对实时性控制的要求比较高,比如赛车游戏,要求以最快速度响应键盘输入。而windows消息由于是队列形式的,消息在传递时会有不少延迟,有时1秒钟也就传递十几条消息,这个速度达不到游戏的要求。而DirectInput则绕过了windows消息,直接与键盘驱动程序打交道,效率当然提高了不少。因此也就造成,对这样的程序无论用PostMessage或者是keybd_event都不会有反应,因为这些函数都在较高层。对于这样的程序,只好用直接读写键盘端口的方法来模拟硬件事件了。
    所以使用win32、uia等方式进行鼠标键盘操作时,在很多游戏中不能成功。
    消息机制:
    在普通的Windows程序中,用户通过键盘或者鼠标输入的消息并不是应用程序直接处理的,而是通过Windows的消息机制转发给Windows操作系统的。Windows操作系统对这些消息进行响应后,在通过回调应用程序的窗口过程函数进行相应的消息处理。
    用户按下键盘上的一个键 >>>>> 键盘控制器就把这个键的扫描码传给计算机,然后交给键盘驱动程序 >>>>> 键盘驱动程序会把这个扫描码转换为键盘虚拟码(VK_A,VK_B这样的常数,比如键A的虚拟码是65,写成16进制就是&H41)传给操作系统 >>>>> 操操作系统则会把这些信息封装在一个消息中,并把这个键盘消息插入到消息列队 >>>>> 键盘消息被发送到当前活动窗口

  2. 现有框架对图像识别的局限性
    sikuli使用的是模板匹配,如果更换了设备,分辨率变了,很可能匹配不上

------------- The End -------------