UI Automation 只适用于,标准的win32和 WPF程序
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Automation; using System.Windows.Forms; namespace WindowsFormsApplication3 { public partial class Form1 : Form { private Process process; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { process = Process.Start(@"C:\Windows\System32\notepad.exe"); } private void button2_Click(object sender, EventArgs e) { process.Kill(); } private void button3_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; // MessageBox.Show(ae.Current.NativeWindowHandle.ToString()); StringBuilder sb = new StringBuilder(); // AutomationElementCollection topWindows = desktop.FindAll(TreeScope.Children, Condition.TrueCondition); //查询所有子元素 AutomationElementCollection topWindows = desktop.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "CalcFrame"));//查找计算器 for (int i = 0; i < topWindows.Count; i++) { AutomationElement topWindow = topWindows[i]; sb.AppendLine("Name:" + topWindow.Current.Name + ";ClassName=" + topWindow.Current.ClassName); } MessageBox.Show(sb.ToString()); } } }
上面是核心实现的代码,下面从环境一步一步来操作。
示例源码工程下载:https://pan.baidu.com/s/1nYuDEtcP4a9RbbtsSXSSFQ
UI Automation 学习视频:http://www.rupeng.com/Courses/Chapter/298#videoDiv
第一步 安装Visual studio 2015 (老研发喜欢 2012)步骤略
第二步 新建项目
文件》新建》项目
第三步新建一个windows>windows窗体应用程序
第四步打开左侧工具箱,拖动button到Form1上,双击form1进行编译
第五步右侧点开引用,在引用上右键添加引用。在程序集里搜索auto,并勾选UIAutomationClient、
UIAutomationProvider、UIAutomationTypes
-Win32基础知识:
1、Win32中一切元素皆窗口,窗口之间有父子关系。整个桌面是一个“根窗口”。
2、进程:
根据进程id拿到进程对象Process process = Process.GetProcessById(processId);
启动一个进程:Process process = Process.Start(exe路径);
杀死一个进程process.Kill()
注意:在Windows 10下,如果Process.Start()启动的calc.exe进程在Kill时候会报错,因为Windows10的calc.exe只是一个跳板,真正最后启动的是Windows10版的计算器,而Windows10的计算器是和以前版本不一样的。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Automation; using System.Windows.Forms; namespace WindowsFormsApplication3 { public partial class Form1 : Form { private Process process; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { process = Process.Start(@"C:\Windows\System32\notepad.exe"); } private void button2_Click(object sender, EventArgs e) { process.Kill(); } private void button3_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; // MessageBox.Show(ae.Current.NativeWindowHandle.ToString()); StringBuilder sb = new StringBuilder(); // AutomationElementCollection topWindows = desktop.FindAll(TreeScope.Children, Condition.TrueCondition); //查询所有子元素 AutomationElementCollection topWindows = desktop.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "CalcFrame"));//查找计算器 for (int i = 0; i < topWindows.Count; i++) { AutomationElement topWindow = topWindows[i]; sb.AppendLine("Name:" + topWindow.Current.Name + ";ClassName=" + topWindow.Current.ClassName); } MessageBox.Show(sb.ToString()); } private void button4_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; var calcFrame1 = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "CalcFrame")); var calcFrame2 = calcFrame1.FindFirst(TreeScope.Children, Condition.TrueCondition); var result = calcFrame2.FindFirst(TreeScope.Children, Condition.TrueCondition); //显示结果窗口 var buttons = calcFrame2.FindAll(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty,"button")); var btn9 = calcFrame2.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "9")); MessageBox.Show(btn9.Current.Name); // var buttons = calcFrame2.FindAll(TreeScope.Children, Condition.TrueCondition); //var keyboardArea = calcFrame2Children[2];//第三个子元素 // var buttons = keyboardArea.FindAll(TreeScope.Children, Condition.TrueCondition); /* StringBuilder sb = new StringBuilder(); for (int i = 0; i < buttons.Count; i++) { AutomationElement btn = buttons[i]; sb.AppendLine(btn.Current.Name); } MessageBox.Show(sb.ToString()); */ } private void button5_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; var calcFrame1 = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "CalcFrame")); Condition conditionBtn6 = new AndCondition( new PropertyCondition(AutomationElement.ClassNameProperty, "Button"), new PropertyCondition(AutomationElement.NameProperty,"6") ); var btn6 = calcFrame1.FindFirst(TreeScope.Children, conditionBtn6); InvokePattern button6Invoke = (InvokePattern)btn6.GetCurrentPattern(InvokePattern.Pattern); button6Invoke.Invoke(); Condition conditionBtnPlus = new AndCondition( new PropertyCondition(AutomationElement.ClassNameProperty, "Button"), new PropertyCondition(AutomationElement.NameProperty, "+") ); var btnPlus = calcFrame1.FindFirst(TreeScope.Children, conditionBtnPlus); InvokePattern buttonPlusInvoke = (InvokePattern)btn6.GetCurrentPattern(InvokePattern.Pattern); buttonPlusInvoke.Invoke(); } private static void InvokeButton(AutomationElement e) { InvokePattern Invoke = (InvokePattern)e.GetCurrentPattern(InvokePattern.Pattern); Invoke.Invoke(); } private static void ClickCalculatorButton(AutomationElement calcFrame1, String name) { Condition conditionBtn = new AndCondition( new PropertyCondition(AutomationElement.ClassNameProperty, "Button"), new PropertyCondition(AutomationElement.NameProperty, name) ); var btn = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn); // MessageBox.Show(btn.Current.Name); if(btn == null) { throw new Exception("找不到此"+ name + "的按钮"); } InvokeButton(btn); } private void button6_Click(object sender, EventArgs e) { AutomationElement desktop = AutomationElement.RootElement; var calcFrame1 = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "CalcFrame")); ClickCalculatorButton(calcFrame1, "3"); ClickCalculatorButton(calcFrame1, "*"); ClickCalculatorButton(calcFrame1, "5"); ClickCalculatorButton(calcFrame1, "5"); ClickCalculatorButton(calcFrame1, "="); } } }
-UIAutomation基础:
1、需要添加对UIAutomationClient、 UIAutomationProvider、 UIAutomationTypes的引用
2、AutomationElement.RootElement是窗口根元素
AutomationElement.FromHandle(IntPtr hwnd)从窗口句柄拿到AutomationElement对象。
3、遍历:
mainElement.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "TLabeledEdit"));
TreeScope.Descendants代表递归从所有子孙元素中递归查找;如果是从直接子节点查找,则使用TreeScope.Children。Condition是过滤条件,可以根据类名等查找,如果是不指定查询条件则使用Condition.True Condition。
FindFirst是查到第一个。
4、点击按钮、设置文本、读取文本使用Pattern来实现。不是所有Pattern都支持
1)设置控件的值:
ValuePattern valuePattern = (ValuePattern)element.GetCurrentPattern(ValuePattern.Pattern);
valuePattern.SetValue("rupeng.com");
2)得到文本控件的值
TextPattern valuePattern = (TextPattern)element.GetCurrentPattern(TextPattern.Pattern);
string v= valuePattern.DocumentRange.GetText(-1);
3)调用控件,比如点击按钮
var clickPattern = (InvokePattern)element.GetCurrentPattern(InvokePattern.Pattern);
clickPattern.Invoke();