基于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.pswp.cn/news/38349.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/38349.shtml
英文地址,請注明出處:http://en.pswp.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表達式…

ubuntu 安裝 python3.9

一、 相關背景 之前在dockerfile里面一直使用的是python3.8&#xff08;忘記為什么選擇這個版本了&#xff09;&#xff0c;想用python3.9&#xff0c;因為覺得3.8有點老了&#xff0c;而且3.9一個重要的feature&#xff0c;是把list作為默認的類型&#xff0c;不需要從typing…

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加載和展示三維地…

【JavaSE】面向對象之封裝

封裝的概念 封裝是把過程和數據包圍起來&#xff0c;對數據的訪問只能通過已定義的接口。面向對象計算始于這個基本概念&#xff0c;即現實世界可以被描繪成一系列完全自治、封裝的對象&#xff0c;這些對象通過一個受保護的接口訪問其他對象。封裝是一種信息隱藏技術&#xff…

Java旋轉數組中的最小數字(圖文詳解版)

目錄 1.題目描述 2.題解 分析 具體實現 方法一&#xff08;遍歷&#xff09;&#xff1a; 方法二&#xff08;排序&#xff09;&#xff1a; 方法三&#xff08;二分查找&#xff09;&#xff1a; 1.題目描述 有一個長度為 n 的非降序數組&#xff0c;比如[1,2,3,4,5]&a…

Linux基礎

Linux 一、基礎01- 執行環境準備02- linux的版本分類02.1 內核版本02.2 發行版本02.3 內核和發行版本的區別: 03- 虛擬機安裝04- 啟動linux 二、系統操作05- 幫助命令05.1 man 幫助05.2 help 幫助05.2.1 內部命令05.2.2 外部命令 05.3 info 幫助 06- ls命令06.1 -r06.2 -rt06.3…

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 …

在Linux中對docker 一鍵安裝,本地安裝,無網絡安裝,

在Linux中對docker 一鍵安裝 前提先準備好安裝包 非常絲滑 首先先把需要準備的文件準備好&#xff0c;/package/base.tar 和 /package/docker-20.10.10.tgz包 這兩個文件包必須放在 /package目錄下 再和/package同級的目錄下再準備conf目錄&#xff0c;conf目錄下放docker.se…

Labview解決“重置VI:xxx.vi”報錯問題

文章目錄 前言一、程序框圖二、前面板三、問題描述四、解決辦法 前言 在程序關閉前面板的時候小概率型出現了 重置VI&#xff1a;xxx.vi 這個報錯&#xff0c;并且發現此時只能通過任務管理器殺掉 LabVIEW 進程才能退出&#xff0c;這里介紹一下解決方法。 一、程序框圖 程序…

特征選擇 | 遞歸特征消除算法篩選最優特征

特征選擇 | 遞歸特征消除算法篩選最優特征 目錄 特征選擇 | 遞歸特征消除算法篩選最優特征寫在前面常規方法算法原理結果分析參考資料 寫在前面 在實際應用中&#xff0c;特征選擇作為機器學習和數據挖掘領域的重要環節&#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 自我記錄 翻譯 選項…

智能家居(2)---串口通信(語音識別)控制線程封裝

封裝語音線程&#xff08;語音通過串口和主控設備進行交流&#xff09;實現對智能家居中各種燈光的控制 mainPro.c(主函數) #include <stdio.h> #include "controlDevice.h" #include "inputCommand.h" #include <pthread.h>struct Devices …

echart 3d立體顏色漸變柱狀圖

如果可以實現記得點贊分享&#xff0c;謝謝老鐵&#xff5e; 1.需求描述 根據業務需求將不同的法律法規&#xff0c;展示不同的3d立體漸變柱狀圖。 2.先看下效果圖 3. 確定三面的顏色&#xff0c;這里我是自定義的顏色 // 右面生成顏色const rightColorArr ref(["#79D…