前段时间应公司要求开发一款针对现有WPF程序的自动化测试工具,在网上查资料找了一段时间,发现用来做自动化测试的框架还是比较多的,比如python的两个模块pywinauto和uiautomation,但是pywinauto主要是封装Win32的api,只局限于winform框架,而python中的uiautomation其实是封装的windows中的uia框架。基于项目效率考虑,所以最后决定使用windows中的UIAutomation框架。

这款WindowsUIA框架是同时支持wpf和winform,由于公司项目主要是wpf为主,所以以下学习和举例也是基于wpf框架,没有深入研究winform下的差异,但是大体上还是差不多的。

仅仅作为客户端来invoke的话,只需要引用下面两个dll即可,可以在.Net框架中查找:UIAutomationClient.dll,UIAutomationTypes.dll

在UIA框架中,所有元素包括窗口和控件都表现为AutomationElement。一个进程中的UI在空间上分布在一棵UI树上面,只需要找到UI树的根元素,就可以检索到与之相关联的其他任何元素

查找窗口

查找每个进程的根元素最常用的是根据控件句柄查找,方法如下:

但是这个框架没有提供检索句柄的功能,所以需要和API配合使用:

private static extern IntPtr findWindow(string lpClassName, string lpWindowName);

根据这个API获取某个窗口的句柄,根据这个窗口的句柄获取到AutomationElement,然后就可以通过下面的方法来查找其他元素

以上两个方法可以搜索到这颗UI树上的所有子控件,例如查找某个Name属性为MyButton的Button控件并触发它的点击事件,就可以这样实现:

PropertyCondition typeProperty = new PropertyCondition(AutomationElement.IsInvokePatternAvailableProperty, true);
PropertyCondition nameProperty = new PropertyCondition(AutomationElement.AutomationIdProperty, “MyButton”);//搜索条件
AutomationElement ele = _mainAutomationElement.FindFirst(TreeScope.Subtree, new AndCondition(typeProperty, nameProperty));
if (ele != null)
{
if (ele.Current.IsEnabled)
{
InvokePattern pattern = (InvokePattern)ele.GetCurrentPattern(InvokePattern.Pattern);
pattern.Invoke();//触发点击事件 } }

  

需要注意的是WPF中控件的属性映射到AutomationElement有以下对应关系

Control property in WPF Property in AutomationElement
Name         AutomationIdProperty
Content   Name
Title   Name

窗口的Title和继承ContentControl 的控件的Content  都会映射为AutomationElement中的Name属性

通过上述方法,基本可以查找到WPF中所有常用的控件,至于三方控件也有一定的兼容性。

基于以上信息,我们可以开发一个小工具,用于读取QQ软件的好友列表。

读取QQ软件的好友列表

​这个小功能还是通过win32API+UIA框架实现的,获取到qq好友列表中的成员备注名称,图中的好友姓名只取姓氏。

用到的API如下:

private const int MOUSEEVENTF_LEFTDOWN = 0x0002;//press the  mouse left button
private const int MOUSEEVENTF_LEFTUP = 0x0004; //release the mouse right button
private const int MOUSEEVENTF_WHEEL = 0x800;//mouse wheel
[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr findWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
[DllImport("user32.dll", EntryPoint = "SetCursorPos")]
private static extern bool setCursorPos(int X, int Y);

第一个API是为了获取qq窗口的句柄,第二个和第三个是用来模拟鼠标操作。

主程序代码很简单,基本流程是先检索到列表名称的控件,然后通过获取坐标控制鼠标点击将列表展开,检索该列表中所有的成员。检索完成后将列表重新隐藏,避免列表成员太多,列表太长,影响下一个列表的展开。

            IntPtr ptr = findWindow(null,"QQ");
List<string> tables = new List<string>() {"高中","小学","初中","网友","大学"};//好友列表名称
AutomationElement _mainElement = AutomationElement.FromHandle(ptr);
foreach (var item in tables)
{
PropertyCondition type = new PropertyCondition(AutomationElement.IsControlElementProperty, true);
PropertyCondition name = new PropertyCondition(AutomationElement.NameProperty, item);
AutomationElement tableElement = _mainElement.FindFirst(TreeScope.Subtree, new AndCondition(type, name));
if(tableElement!=null)
{
Click(tableElement.GetClickablePoint().X, tableElement.GetClickablePoint().Y);//展开列表
AutomationElementCollection ac = _mainElement.FindAll(TreeScope.Subtree, new PropertyCondition(AutomationElement.IsSelectionItemPatternAvailableProperty, true));
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(tableElement.Current.Name+":");
Console.ForegroundColor = ConsoleColor.White;
foreach (AutomationElement ele in ac)
{
Console.WriteLine(ele.Current.Name.Substring(0, 1) + "**");
}
Click(tableElement.GetClickablePoint().X, tableElement.GetClickablePoint().Y);//重新隐藏列表
} } Console.ReadLine();

  

通过控制鼠标的API和UIA框架基本可以实现模拟任何人为操作,对实现windows app自动化测试是一个不错的选择

Windows UIA自动化测试框架学习--获取qq好友列表的更多相关文章

  1. C# 获取QQ好友列表信息的实现

    分析部分 当我们访问QQ空间的时候,大家可以在右侧的发现一个这样的统计信息  当点击这个链接的时候,会跳转到  这样一个URL 这个URl可以管理好友,当然也就能读取到好友  上面我们是在浏览器中的操 ...

  2. App自动化测试框架学习探索--从零开始设计

    App自动化测试框架学习探索--从零开始设计---持续更新中,敬请关注 1 批量执行app自动化测试使用多线程设计思路: 1)并发级别选择用methods 2)采用@Test多线程,数据提供类dp单线 ...

  3. (二十七)QQ好友列表的实现

    QQ好友列表通过plist读取,plist的结构为一组字典,每个字典内有本组的信息和另外一组字典代表好友. 要读取plist,选择合适的数据结构,例如NSArray,然后调用initWithConte ...

  4. 基于Qt的相似QQ好友列表抽屉效果的实现

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/shuideyidi/article/details/30619167     前段时间在忙毕业设计, ...

  5. iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一)

    iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一) 一.项目结构和plist文件 二.实现代码 1.说明: 主控制器直接继承UITableViewController // ...

  6. [iOS基础控件 - 6.9.3] QQ好友列表Demo TableView

    A.需求 1.使用plist数据,展示类似QQ好友列表的分组.组内成员显示缩进功能 2.组名使用Header,展示箭头图标.组名.组内人数和上线人数 3.点击组名,伸展.缩回好友组   code so ...

  7. 仿QQ好友列表界面的实现

    TableView有2种style:UITableViewStylePlain 和 UITableViewStyleGrouped. 但是QQ好友列表的tableView给人的感觉似乎是2个style ...

  8. ExpandableListView仿QQ好友列表

    本例中,对ExpandableListView中的数据进行了封装,分为两个JavaBean,一个为Group类表示组信息,一个Child类表示该组下子列表信息: Group: public class ...

  9. android 实现QQ好友列表

    在某些Android开发群里,看到有些新手问怎么实现QQ好友列表,其实网上一搜挺多的.接触Android,也才一年的时间,大部分时间花在工作上(解bug...),界面上开发很少参与.自己维护的系统应用 ...

随机推荐

  1. 详细描述一下 Elasticsearch 更新和删除文档的过程?

    1.删除和更新也都是写操作,但是 Elasticsearch 中的文档是不可变的,因此不 能被删除或者改动以展示其变更: 2.磁盘上的每个段都有一个相应的.del 文件.当删除请求发送后,文档并没有真 ...

  2. Java Lambda详解

    Lambda表达式是JDK 8开始后的一种新语法形式. 作用:简化匿名内部类的代码写法 简化格式 (匿名内部类被重写方法的形参列表) -> { 重写方法 } Lambda表达式只能简化函数式接口 ...

  3. 搞懂高并发性能指标:QPS、TPS、RT、吞吐量

      一.QPS,每秒查询 QPS:Queries Per Second意思是"每秒查询率",是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的 ...

  4. Apollo模块文章

    Apollo规划模块 自动驾驶公开课 | Apollo 2.5自动驾驶规划控制 : 这篇资料比较早,但是把EM Planner和Lattice Planner这两种在资料上经常看到的算法的来历和大概原 ...

  5. 基于react的audio组件

    样式请自己定义哦~需要其他功能请自行添加! // 组件调用 <Audio src={src地址} id={srcID}/> audio属性 src 歌曲的路径 preload 是否在页面加 ...

  6. 原型模式故事链--new一个对象的过程

    上一个总标题:https://segmentfault.com/a/11...提问:你有对象了吗?答:没有.笨!new一个不就好了吗! 问题点:为什么我要理解new一个对象的过程?答:不理解这个过程, ...

  7. Java中读取 .properties 和 .xml 文件

    配置文件内容获取 总结内容 1. Java中为什么要使用配置文件 2. Java中常用的配置文件类型有哪些以及它们的特点 Properties配置文件 XML配置文件 总结 总结内容 1. Java中 ...

  8. Java Web项目与Java项目的区别

    一.以下是我对Java Web项目和Java项目这两者的理解以及区别: 1.Java Web项目是基于Java EE类的:而Java项目是基于Java应用程序的. 2.Java Web项目是网页的编码 ...

  9. 移动端input输入框把页面顶起, 收起键盘页面复原不了问题

    我相信大家平时也会遇到这种问题, 移动端 input 或者 textarea获取光标, 整个页面被顶起来, 键盘收起, 页面不复原的问题 ====>>>>  我这边提供两种解决 ...

  10. css3,css的基础全局运用

    浮动 1.浮动起来的盒子不占用位置,浮动了一个盒子下面的标准流的盒子会顶上来 ​ 可用清除浮动的方法来解决标准流会顶替位置的问题 清除浮动给父盒子加overflow: hidden; 鼠标经过事件 : ...