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();
一个有趣的微信控制实验
https://blog.csdn.net/as604049322/article/details/119899542