UIAutomation操作

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

你可能感兴趣的:(C#,wpf,ui,windows)