基于C#UI Automation自动化测试

步骤

UI Automation 只适用于,标准的win32和 WPF程序

需要添加对UIAutomationClient、 UIAutomationProvider、 UIAutomationTypes的引用

代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Automation;
using System.Windows.Forms;
using System.Windows.Input;namespace WindowsFormsApp1
{public partial class Form1 : Form{private Process processnotepad;private Process processcalc;public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){//打开笔记本processnotepad = Process.Start(@"C:\Windows\System32\notepad.exe");}private void button2_Click(object sender, EventArgs e){//关闭笔记本processnotepad.Kill();}private void button3_Click(object sender, EventArgs e){//AutomationElement表示 UI 自动化树中的一个 UI 自动化元素,并包含由 UI 自动化客户端应用程序用作标识符的值。//获取当前桌面的根 AutomationElement。AutomationElement desktop = AutomationElement.RootElement;//StringBuilder不在内存中创建新对象,而是动态扩展内存以容纳修改后的字符串。StringBuilder sb = new StringBuilder();//TreeScope(枚举)包含指定 UI 自动化目录树内元素的范围的值。具体参考请点击以下链接进行查看//TreeScope官方链接:https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.automation.treescope?view=windowsdesktop-7.0AutomationElementCollection topWindows = desktop.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));//查找计算器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, "ApplicationFrameWindow"));AutomationElementCollection btn2 = calcFrame1.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "num9Button"));AutomationElement btn = btn2[0];MessageBox.Show(btn.Current.Name);}private void button5_Click(object sender, EventArgs e){AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));Condition conditionBtn6 = new AndCondition(new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),new PropertyCondition(AutomationElement.NameProperty, "六"));var btn6 = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn6);//InvokePattern 表示用于启动或执行单个明确操作的控件,并且这些控件在激活时不保持其状态。//InvokePattern.Pattern 标识 InvokePattern 控件模式。//InvokePattern官方链接 https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.automation.invokepattern?view=windowsdesktop-7.0InvokePattern button6Invoke = (InvokePattern)btn6.GetCurrentPattern(InvokePattern.Pattern);//Invoke() 发送请求以激活控件并启动其单一、明确的操作。button6Invoke.Invoke();Condition conditionBtnPlus = new AndCondition(new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),new PropertyCondition(AutomationElement.NameProperty, "加"));var btnPlus = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtnPlus);InvokePattern buttonPlusInvoke = (InvokePattern)btnPlus.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, "ApplicationFrameWindow"));ClickCalculatorButton(calcFrame1, "三");ClickCalculatorButton(calcFrame1, "乘以");ClickCalculatorButton(calcFrame1, "五");ClickCalculatorButton(calcFrame1, "五");ClickCalculatorButton(calcFrame1, "等于");}[DllImport("user32.dll")]public static extern void SetCursorPos(int x, int y);[DllImport("user32.dll")]public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);private void button7_Click(object sender, EventArgs e){AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));Condition conditionBtn6 = new AndCondition(new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),new PropertyCondition(AutomationElement.NameProperty, "六"));var btn6 = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn6);SetCursorPos((int)btn6.GetClickablePoint().X, (int)btn6.GetClickablePoint().Y);//mouse_event(0x0002 | 0x0004, 0, 0, 0, 0);mouse_event(0x0002, 0, 0, 0, 0);  // 模拟鼠标左键按下mouse_event(0x0004, 0, 0, 0, 0);  // 模拟鼠标左键弹起}private void button8_Click(object sender, EventArgs e){AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));Condition conditionEdit = new AndCondition( new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"), new PropertyCondition(AutomationElement.NameProperty, "文本编辑器"));AutomationElement txtEdit = calcFrame1.FindFirst(TreeScope.Descendants, conditionEdit);txtEdit.SetFocus();SendKeys.Send("追加123456789");}private const int WM_SETTEXT = 0x000C;[DllImport("user32.dll")]private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);[DllImport("User32.dll")]private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindows);[DllImport("User32.dll")]private static extern Int32 SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam);private void button9_Click(object sender, EventArgs e){AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));Condition conditionEdit = new AndCondition(new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"), new PropertyCondition(AutomationElement.NameProperty, "文本编辑器"));AutomationElement txtEdit = calcFrame1.FindFirst(TreeScope.Descendants, conditionEdit);//.NET提供了一个结构体System.IntPtr专门用来代表句柄或指针。//句柄是对象的标识符,当调用这些API创建对象时,它们并不直接返回指向对象的指针,//而是会返回一个32位或64位的整数值,这个在进程或系统范围内唯一的整数值就是句柄(Handle),//随后程序再次访问对象,或者删除对象,都将句柄作为Windows API的参数来间接对这些对象进行操作。//句柄是一个结构体,简单的来说,它是指针的一个封装,是C#中指针的替代者//句柄链接:https://blog.csdn.net/sinat_40003796/article/details/127244155IntPtr hWnd = FindWindow("Notepad", null);if (!hWnd.Equals(IntPtr.Zero)){IntPtr edithWnd = FindWindowEx(hWnd, IntPtr.Zero, "Edit", null);if (!edithWnd.Equals(IntPtr.Zero)){SendMessage(edithWnd, WM_SETTEXT, IntPtr.Zero, new StringBuilder("重写123456789"));}}else{}}private void button10_Click(object sender, EventArgs e){//点击后有列表的按钮不要当成点击事件AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, "编辑(E)");AutomationElement w2 = calcFrame1.FindFirst(TreeScope.Descendants, myCondition2);ExpandCollapsePattern ecp = (ExpandCollapsePattern)w2.GetCurrentPattern(ExpandCollapsePattern.Pattern);ecp.Expand();}private AutomationElement autoElementGet1(AutomationElement e, string s){Condition myCondition1 = new PropertyCondition(AutomationElement.AutomationIdProperty, s);Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, s);Condition myCondition3 = new PropertyCondition(AutomationElement.AcceleratorKeyProperty, s);Condition myCondition4 = new PropertyCondition(AutomationElement.ClassNameProperty, s);Condition myCondition5 = new PropertyCondition(AutomationElement.AccessKeyProperty, s);Condition myCondition6 = new PropertyCondition(AutomationElement.LocalizedControlTypeProperty, s);Condition myCondition = new OrCondition(myCondition1, myCondition2, myCondition3, myCondition4, myCondition5,myCondition6);AutomationElementCollection myCollection = e.FindAll(TreeScope.Descendants, myCondition);return myCollection[0];}private void button11_Click(object sender, EventArgs e){//随机元素获取AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));AutomationElement filename = autoElementGet1(calcFrame1, "文件(F)");MessageBox.Show("Name:" + filename.Current.Name + ";ClassName=" + filename.Current.ClassName);}private void button12_Click(object sender, EventArgs e){//遍历子控件AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));Condition myCondition1 = new PropertyCondition(AutomationElement.AutomationIdProperty, "MenuBar");AutomationElement MenuBar = calcFrame1.FindFirst(TreeScope.Descendants, myCondition1);AutomationElementCollection MenuBarChildAll = MenuBar.FindAll(TreeScope.Children, Condition.TrueCondition);for (int i = 0; i < MenuBarChildAll.Count; i++){AutomationElement MenuBarChild = MenuBarChildAll[i];MessageBox.Show("Name:" + MenuBarChild.Current.Name + ";ClassName=" + MenuBarChild.Current.ClassName + ";ControlType=" + MenuBarChild.Current.ControlType);}}private void button13_Click(object sender, EventArgs e){processcalc = Process.Start(@"C:\Windows\System32\calc.exe");}private void button14_Click(object sender, EventArgs e){processcalc.Kill();}private void button15_Click(object sender, EventArgs e){//点击后有列表的按钮不要当成点击事件AutomationElement desktop = AutomationElement.RootElement;var calcFrame1 = desktop.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));Condition myCondition1 = new PropertyCondition(AutomationElement.NameProperty, "文件(F)");AutomationElement w1 = calcFrame1.FindFirst(TreeScope.Descendants, myCondition1);ExpandCollapsePattern ecp = (ExpandCollapsePattern)w1.GetCurrentPattern(ExpandCollapsePattern.Pattern);ecp.Expand();Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, "退出(X)");AutomationElementCollection myCollection = w1.FindAll(TreeScope.Descendants, myCondition2);AutomationElement w2 = myCollection[0];InvokePattern ipn = (InvokePattern)w2.GetCurrentPattern(InvokePattern.Pattern);ipn.Invoke();Thread.Sleep(500);AutomationElement savefile = calcFrame1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "保存(S)"));if (savefile != null){InvokePattern savefilebutton = (InvokePattern)savefile.GetCurrentPattern(InvokePattern.Pattern);savefilebutton.Invoke();Thread.Sleep(500);AutomationElement Saveasform = calcFrame1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "另存为"));AutomationElement edit1 = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "1001"));ValuePattern vp = (ValuePattern)edit1.GetCurrentPattern(ValuePattern.Pattern);vp.SetValue("aaa.txt");AutomationElement savefilepath = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "保存(S)"));InvokePattern savefilepathbutton = (InvokePattern)savefilepath.GetCurrentPattern(InvokePattern.Pattern);savefilepathbutton.Invoke();Thread.Sleep(500);AutomationElement yesSaveasform = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "确认另存为"));AutomationElement issavefilepath = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "是(Y)"));if (issavefilepath != null) {InvokePattern issavefilepathbutton = (InvokePattern)issavefilepath.GetCurrentPattern(InvokePattern.Pattern);issavefilepathbutton.Invoke();}}}}
}

各按钮的功能展示

打开记事本

关闭记事本

获取计算器窗体

修改对应代码,每个按钮点击事件下的的该属性都需要进行修改

 结果

获取控件属性

 结果

点击按钮

完成计算器计算

 鼠标点击按钮

功能是让鼠标去点击,实现点击按钮的功能

 追加记事本内容

原始

运行

 重写记事本内容

展开按钮列表

随机获取元素方法

遍历记事本菜单栏

打开计算器

控件关闭计算器

 保存记事本

工程示例

https://download.csdn.net/download/qq_39397927/88215681

参考

https://www.cnblogs.com/baihuitestsoftware/articles/9047705.html

UI自动化 --- 微软UI Automation_dotNET跨平台的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/38349.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++11并发与多线程笔记(2)

C11并发与多线程笔记&#xff08;2&#xff09; 线程启动、结束&#xff0c;创建线程多法、join&#xff0c;detach 1. 范例演示线程运行的开始1.1 创建一个线程&#xff1a;1.2 join1.3 datch1.4 joinable 2. 其他创建线程的方法2.1 用类 重载了函数调用运算符2.2 lambda表达式…

Redis数据结构——Redis简单动态字符串SDS

定义 众所周知&#xff0c;Redis是由C语言写的。 对于字符串类型的数据存储&#xff0c;Redis并没有直接使用C语言中的字符串。 而是自己构建了一个结构体&#xff0c;叫做“简单动态字符串”&#xff0c;简称SDS&#xff0c;比C语言中的字符串更加灵活。 SDS的结构体是这样的…

Python-OpenCV中的图像处理-视频分析

Python-OpenCV中的图像处理-视频分析 视频分析Meanshift算法Camshift算法光流 视频分析 学习使用 Meanshift 和 Camshift 算法在视频中找到并跟踪目标对象: Meanshift算法 Meanshift 算法的基本原理是和很简单的。假设我们有一堆点&#xff08;比如直方 图反向投影得到的点&…

ASR 语音识别接口封装和分析

这个文档主要是介绍一下我自己封装了 6 家厂商的短语音识别和实时流语音识别接口的一个包&#xff0c;以及对这些接口的一个对比。分别是&#xff0c;阿里&#xff0c;快商通&#xff0c;百度&#xff0c;腾讯&#xff0c;科大&#xff0c;字节。 zxmfke/asrfactory (github.c…

ubuntu 安装 cuda

ubuntu 安装 cuda 初环境与设备在官网找安装方式 本篇文章将介绍ubuntu 安装 CUDA Toolkit CUDA Toolkit 是由 NVIDIA&#xff08;英伟达&#xff09;公司开发的一个软件工具包&#xff0c;用于支持并优化 GPU&#xff08;图形处理器&#xff09;上的并行计算和高性能计算。它…

解析TCP/IP协议的分层模型

了解ISO模型&#xff1a;构建通信的蓝图 为了促进网络应用的普及&#xff0c;国际标准化组织&#xff08;ISO&#xff09;引入了开放式系统互联&#xff08;Open System Interconnect&#xff0c;OSI&#xff09;模型。这个模型包括了七个层次&#xff0c;从底层的物理连接到顶…

一、Dubbo 简介与架构

一、Dubbo 简介与架构 1.1 应用架构演进过程 单体应用&#xff1a;JEE、MVC分布式应用&#xff1a;SOA、微服务化 1.2 Dubbo 简介一种分布式 RPC 框架&#xff0c;对专业知识&#xff08;序列化/反序列化、网络、多线程、设计模式、性能优化等&#xff09;进行了更高层的抽象和…

ArcGIS Maps SDK for JavaScript系列之三:在Vue3中使用ArcGIS API加载三维地球

目录 SceneView类的常用属性SceneView类的常用方法vue3中使用SceneView类创建三维地球项目准备引入ArcGIS API创建Vue组件在OnMounted中调用初始化函数initArcGisMap创建Camera对象Camera的常用属性Camera的常用方法 要在Vue 3中使用ArcGIS API for JavaScript加载和展示三维地…

Java旋转数组中的最小数字(图文详解版)

目录 1.题目描述 2.题解 分析 具体实现 方法一&#xff08;遍历&#xff09;&#xff1a; 方法二&#xff08;排序&#xff09;&#xff1a; 方法三&#xff08;二分查找&#xff09;&#xff1a; 1.题目描述 有一个长度为 n 的非降序数组&#xff0c;比如[1,2,3,4,5]&a…

npm install 中 --save 和 --save-dev 是什么?

npm&#xff0c;全名 Node Package Manager&#xff0c;套件管理工具&#xff0c;package.json 会记下你在项目中安装的所有套件。 假设在项目中安装 lodash npm i --save lodash这样在 dependencies 中会出现&#xff1a; 如果修改了导入方式&#xff1a; npm i --save-dev …

Labview解决“重置VI:xxx.vi”报错问题

文章目录 前言一、程序框图二、前面板三、问题描述四、解决办法 前言 在程序关闭前面板的时候小概率型出现了 重置VI&#xff1a;xxx.vi 这个报错&#xff0c;并且发现此时只能通过任务管理器杀掉 LabVIEW 进程才能退出&#xff0c;这里介绍一下解决方法。 一、程序框图 程序…

pve7.2虚拟机 lvm磁盘扩容,增加硬盘操作

之前安装pve时候只有256的ssd,最近安装的虚拟机较多&#xff0c;给加块闲置硬盘&#xff0c;顺便学习一下&#xff0c;像pve这种虚拟机系统&#xff0c;硬盘应该可以像nas你这样随时增加&#xff0c;而不影响上层应用&#xff0c;我自己也是摸索着做。 一、安装好硬盘后打开pv…

vue3+ts-tsconfig.json报错Option ‘importsNotUsedAsValues’

vue3ts-tsconfig.json报错Option ‘importsNotUsedAsValues’ is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption ‘“ignoreDeprecations”: “5.0”’ to silence this error. Use ‘verbatimModuleSyntax’ instead 自我记录 翻译 选项…

echart 3d立体颜色渐变柱状图

如果可以实现记得点赞分享&#xff0c;谢谢老铁&#xff5e; 1.需求描述 根据业务需求将不同的法律法规&#xff0c;展示不同的3d立体渐变柱状图。 2.先看下效果图 3. 确定三面的颜色&#xff0c;这里我是自定义的颜色 // 右面生成颜色const rightColorArr ref(["#79D…

ComponentOne Studio ASP.NET MVC Crack

ComponentOne Studio ASP.NET MVC Crack FlexReport增强功能 添加了对在Microsoft Windows上部署Microsoft Azure的支持。 添加了对显示嵌入字体的支持。 .NET标准版的经典C1PDF(Beta版) GrapeCity的经典C1Pdf库现在提供了基于Microsoft.NET标准的版本。在任何.NET应用程序(包括…

江南大学计算机考研分析

24计算机考研|上岸指南 江南大学 江南大学计算机考研招生学院是人工智能与计算机学院。目前均已出拟录取名单。 江南大学人工智能与计算机学院成立于2020年3月&#xff0c;办学历史可追溯到1994年设立的计算机应用专业。学院秉持江南大学“彰显轻工特色&#xff0c;服务国计民…

【数据结构】栈和队列

【数据结构】栈和队列 一&#xff1a; 栈1.栈的概念及和结构2. 栈的实用3. 栈接口实现 二&#xff1a; 队列1. 队列的概念和结构2. 队列的实用3. 队列接口实现 三&#xff1a;扩展 一&#xff1a; 栈 1.栈的概念及和结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许…

SAP安全库存-安全库存共享、安全库存简介

SAP系统中的安全库存用于管理计划外和计划内的库存需求,在某些行业中,由于不同的情况,如意外损耗、损坏、环境问题、制造工艺问题、需求增加等,通常会出现意外的库存需求。 SAP提供了维护安全库存的处理方式来处理这样的问题,安全库存的字段信息在主数据视图中,在物料需…

题解 | #1002.Shortest path# 2023杭电暑期多校9

1002.Shortest path 签到题 记忆化搜索 题目大意 给定一个正整数 n n n &#xff0c;可以对其进行以下操作&#xff1a; 如果 n n n 能被 3 3 3 整除&#xff0c;则可以使 n n / 3 nn/3 nn/3 ;如果 n n n 能被 2 2 2 整除&#xff0c;则可以使 n n / 2 nn/2 nn/2 …

【C++】deque容器

0.前言 1.deque构造函数 #include <iostream> using namespace std; #include <deque>//deque构造函数 void printDeque(const deque<int>& d) {for (deque<int>::const_iterator it d.begin(); it ! d.end(); it){//*it 100; //加了const就不能…