【视频教程】使用UIAutomation开发软件外挂
UIAutomation是.Net 3.5之后提供的“界面自动化测试”技术,本来是给测试人员用的,不过UIAutomation由于也是界面自动操作的技术,比直接使用keybd_event、GetWindowText等Win32的API进行界面模拟操作简单很多,因此也可以用UIAutomation做软件的“外挂”。
我手头正好有这样一个需求,如鹏网有一个内部使用的一个工具(购买的第三方软件),用于根据学生的机器码计算“播放密码”,这个工具只提供了图形化的界面:
输入机器码之后点击【创建播放密码】按钮就能生成播放密码。
如鹏网第二期学习辅助系统的开发中需要开发“自动生成播放密码”的功能,也就是学生在浏览器中输入他的机器码,网站自动计算他的播放密码。
由于这个工具只提供了图形化的界面,没有提供API,所以我就想到使用模拟点击的方法来进行“自动化”,直接使用Win32太麻烦,AutoIt使用还要注册组件,因此就想到了UIAutomation。
完成的效果如下:
下面分享一下主要技术。
学习UIAutomation之前一定要知道,Windows中的程序界面元素都是由“窗口组成的”(DirectUI等除外),按钮、文本框等都是窗口,窗口之间也有父子关系。Windows桌面是所有窗口的根窗口。
UIAutomation支持普通Win32程序(不是VC++、.Net开发的也支持,因为本质上都是Win32程序)和WPF程序,但是不支持普通的DirectUI窗口(比如QQ、浏览器)。
使用UIAutomation之前先要添加对UIAutomationClient、 UIAutomationProvider、 UIAutomationTypes三个程序集的引用。所有的界面元素都是由AutomationElement组成,每个窗口就是一个AutomationElement,因此AutomationElement之前也有父子结构。
可以使用AutomationElement.RootElement获得桌面的根元素;使用AutomationElement.FromHandle(IntPtr hwnd)从Win32窗口句柄拿到AutomationElement对象。
拿到一个AutomationElement通常要遍历他的子元素。遍历子元素之前需要先了解“遍历条件”的概念,遍历条件就是按照什么样的条件去搜索子元素。所有的条件都继承自Condition类,Condition类的主要子类有PropertyCondition、AndCondition 、NotCondition 、OrCondition,这些之类之间可以进行复合的组合,形成各种复杂的遍历条件。
PropertyCondition是根据属性的名字和值进行过滤的。它构造函数的第一个参数为属性的名字,所有支持的属性都在AutomationElement的***Property这些静态成员中;构造函数的第二个参数为被比较的值。又可以使用AndCondition、NotCondition、OrCondition把各个条件进行复杂的逻辑组合。比如下面的conditionBtn9就是“类名为Button并且名字为9”的条件:
Condition conditionBtn9 = new AndCondition( new PropertyCondition(AutomationElement.ClassNameProperty, "Button"), new PropertyCondition(AutomationElement.NameProperty, "9") );
Condition类有两个固定的值,Condition. TrueCondition代表永远为True的条件,Condition. FalseCondition代表永远为False的条件(应该很少用)
我们可以使用AutomationElement的FindAll或者FindFirst方法进行元素的遍历。FindAll是获取所有符合遍历条件的AutomationElement,因此是返回AutomationElementCollection集合,而FindFirst是返回第一个符合遍历条件的AutomationElement,因此是返回AutomationElement。
FindFirst、FindAll的第一个参数代表搜索的范围,最常用的就是TreeScope.Children和TreeScope.Descendants,TreeScope.Children代表在直接子节点中搜索,而TreeScope.Descendants代表递归的在所有子孙节点中搜索。FindFirst、FindAll的第二个参数代表搜索条件。
定位到要操作的AutomationElement之后,可以进行模拟点击(比如按钮)或者读写值(比如输入框)。比如下面的代码中element指向的是一个按钮,下面的代码就是模拟点击这个按钮:
var clickPattern = (InvokePattern)element.GetCurrentPattern(InvokePattern.Pattern); clickPattern.Invoke();
比如下面的代码中element指向的是一个文本框,下面的代码就是使用字符串填充这个输入框:
ValuePattern valuePattern = (ValuePattern)element.GetCurrentPattern(ValuePattern.Pattern); valuePattern.SetValue(“如鹏网”);
下面是我实现的一个模拟点击计算器计算两个数的乘法的数:
AutomationElement desktop = AutomationElement.RootElement; var calcFrame1 = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "CalcFrame")); ClickCalcButton(calcFrame1, "3"); ClickCalcButton(calcFrame1, "6"); ClickCalcButton(calcFrame1, "5"); ClickCalcButton(calcFrame1, "*"); ClickCalcButton(calcFrame1, "1"); ClickCalcButton(calcFrame1, "2"); ClickCalcButton(calcFrame1, "=");
其中ClickCalcButton是我封装的一个方法:
private static void InvokeButton(AutomationElement e) { InvokePattern invoke = (InvokePattern)e.GetCurrentPattern(InvokePattern.Pattern); invoke.Invoke(); } private static void ClickCalcButton(AutomationElement calcFrame1, string name) { Condition conditionBtnPlus = new AndCondition( new PropertyCondition(AutomationElement.ClassNameProperty, "Button"), new PropertyCondition(AutomationElement.NameProperty, name) ); var btn = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtnPlus); if (btn == null) { throw new Exception("找不到名字为"+name+"的计算器按钮"); } InvokeButton(btn); }
文章篇幅有限,特别是对于一些没有Win32基础的朋友,光看上面的文字会不太容易懂,因此我录制了一套大约90分的视频教程,详细的讲解了UIAutomation的使用,希望能够帮到大家。
视频教程地址如下 http://www.rupeng.com/Courses/Chapter/298
【视频教程】使用UIAutomation开发软件外挂的更多相关文章
- Psp个人软件开发软件需求分析和用例分析
Psp个人软件开发软件需求分析和用例分析 一.需求分析 1.业务需求 1.1 应用背景 开发项目进度计划总是那么不明确,延期经常出现,甚至无法给出一个相对比较明确的延迟时间.这样给市场的推广会带来很大 ...
- android开发软件
android开发软件: http://developer.android.com/sdk/index.html#download
- ARM开发软件ADS教程
ARM开发软件ADS教程 ADS(ARM Developer Suite)是ARM公司推出ARM集成开发环境,操作简单方便,获得广大开发人员的青睐.下面使用ADS v1.2做一个实例教程,帮助大家学会 ...
- 在“非软件企业”开发软件的困局 ZT
软件产品广泛服务于各行业,其开发具有高科技.高投入.高产出.高风险的特点.在项目开发和软件应用中,只有将人员能力的发挥与科学技术的使用应用市场的认识进行最佳的融合,才能发挥软件的效益.普通企业虽涉足软 ...
- 10款 Mac 经典原型设计开发软件推荐
在Mac上有大量强大的开发和设计工具,今天和大家推荐10款Mac上的经典原型设计开发工具,原型设计工具是开发者必备的一款工具,无论是网站开发还是移动APP开发,都需要在前期进行严格细致的原型设计,才能 ...
- Java开发软件安装及配置
2017-6-1 1.jdk 1.8.0_131 安装JDK 选择安装目录 安装过程中会出现两次 安装提示 . 第一次是安装 jdk ,第二次是安装 jre .建议两个都安装在同一个java文件夹中的 ...
- 【三分钟视频教程】iOS开发中 Xcode 报 apple-o linker 错误的#解决方案#
[三分钟视频教程]iOS开发中 Xcode 报 apple-o linker 错误的#解决方案# 同样的道理,指向同一库文件的代码语句如果重复书写,即使重复书写所在的文件名字不同,同样会造成这 ...
- Linux下与Windows下开发软件
Linux下开发程序可以完全发挥自己的聪明才智,因为系统内核是完全开放的.Windows下开发程序就稍微郁闷一点,不论何种语言都必须在调用系统API的基础上开发,因为系统内核是不开放的. 这两种系统正 ...
- 苹果Swift可为Windows/Android开发软件了
http://www.swifthumb.com/article-189-1.html http://iphone.tgbus.com/news/class/201502/20150211103418 ...
随机推荐
- Android进程间的通信之Messenger
Android进程间的通信方式可以通过以下两种方式完成: Android接口定义语言(AIDL) 使用Messenger绑定服务 本文我们将学习使用Messenger绑定服务的方式进行进程间的通信. ...
- (三)Bootstrap.jar
catalina.bat 在最后启动了bootstrap.jar, 传递了start作为参数(如果多个参数的话,start在尾部). 然后org.apache.catalina.startup.Boo ...
- .Net判断一个对象是否为数值类型
这乍一听是个很简单的事,但突然搞起来还真有点无从下手的感觉. 首先当然是通过GetType()方法反射获取其类型信息,然后对其进行分析,但是类型信息Type中并没有简单地给出这么一个属性进行判断. 老 ...
- 巧妙地用二叉树完成算式计算算法<计算器,二叉树,C++,独辟蹊径>
#01.引言,我们知道算式计算的问题是栈里面一个非常经典的题目.但是用栈来实现是一个非常麻烦的过程,第一要解决算式判断,是否为符合规则的算式,第二要由中最表达式转化为后缀表达式.这两个部分是栈实现计算 ...
- Codeforces 731C. Socks 联通块
C. Socks time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard input o ...
- DSP(1) -- 离散时间信号的序列类型
1.单位采样序列δ(n):在MATLAB 中函数zeros(1,N)产生一个由N个零组成的列向量.它可用来实现有限区间的δ(n).然而,更高明的方法是利用逻辑关系式n==0来实现δ(n). 2.单位阶 ...
- cxf+spring+数字签名开发webservice(二)
场景 上一章中的webservice接口,因为现场正式环境的项目与外部单位网络不通,是通过前置机与外部进行数据交换,所以我们将webservice部署在前置机,在使用HttpURLCo ...
- gcc与gdb版本兼容问题
今天在用gdb调试C++程序的时候,想用"p i”命令打印出程序的一个局部变量i,却一直提示: No symbol "i" in current context. 我愣了 ...
- 【Mail】搭建邮件服务器(LAMP+Postfix+Dovcot+PostfixAdmin+Roundcubemail)
大纲 一.mail部署说明 二.安装准备 三.LMAP环境配置 四.配置postfixadmin 五.配置postfix 六.配置dovecot 七.测试SMTP和POP3服务 八.配置Roundcu ...
- C#语言基础— 输入与输出
C#语言基础— 输入与输出 1.1函数的四要素:名称.输入.输出.加工 1.2主函数:输出语句.输入语句: Static viod Main(string[] stgs)//下划线部分可以自己指定 { ...