当前位置:   article > 正文

基于C#UI Automation自动化测试_c# 自动化测试

c# 自动化测试

步骤

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

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

代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Linq;
  8. using System.Runtime.InteropServices;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Windows.Automation;
  13. using System.Windows.Forms;
  14. using System.Windows.Input;
  15. namespace WindowsFormsApp1
  16. {
  17. public partial class Form1 : Form
  18. {
  19. private Process processnotepad;
  20. private Process processcalc;
  21. public Form1()
  22. {
  23. InitializeComponent();
  24. }
  25. private void button1_Click(object sender, EventArgs e)
  26. {
  27. //打开笔记本
  28. processnotepad = Process.Start(@"C:\Windows\System32\notepad.exe");
  29. }
  30. private void button2_Click(object sender, EventArgs e)
  31. {
  32. //关闭笔记本
  33. processnotepad.Kill();
  34. }
  35. private void button3_Click(object sender, EventArgs e)
  36. {
  37. //AutomationElement表示 UI 自动化树中的一个 UI 自动化元素,并包含由 UI 自动化客户端应用程序用作标识符的值。
  38. //获取当前桌面的根 AutomationElement。
  39. AutomationElement desktop = AutomationElement.RootElement;
  40. //StringBuilder不在内存中创建新对象,而是动态扩展内存以容纳修改后的字符串。
  41. StringBuilder sb = new StringBuilder();
  42. //TreeScope(枚举)包含指定 UI 自动化目录树内元素的范围的值。具体参考请点击以下链接进行查看
  43. //TreeScope官方链接:https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.automation.treescope?view=windowsdesktop-7.0
  44. AutomationElementCollection topWindows = desktop.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));//查找计算器
  45. for (int i = 0; i < topWindows.Count; i++)
  46. {
  47. AutomationElement topWindow = topWindows[i];
  48. sb.AppendLine("Name:" + topWindow.Current.Name + ";ClassName=" + topWindow.Current.ClassName);
  49. }
  50. MessageBox.Show(sb.ToString());
  51. }
  52. private void button4_Click(object sender, EventArgs e)
  53. {
  54. AutomationElement desktop = AutomationElement.RootElement;
  55. var calcFrame1 = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));
  56. AutomationElementCollection btn2 = calcFrame1.FindAll(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "num9Button"));
  57. AutomationElement btn = btn2[0];
  58. MessageBox.Show(btn.Current.Name);
  59. }
  60. private void button5_Click(object sender, EventArgs e)
  61. {
  62. AutomationElement desktop = AutomationElement.RootElement;
  63. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  64. new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));
  65. Condition conditionBtn6 = new AndCondition(
  66. new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
  67. new PropertyCondition(AutomationElement.NameProperty, "六")
  68. );
  69. var btn6 = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn6);
  70. //InvokePattern 表示用于启动或执行单个明确操作的控件,并且这些控件在激活时不保持其状态。
  71. //InvokePattern.Pattern 标识 InvokePattern 控件模式。
  72. //InvokePattern官方链接 https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.automation.invokepattern?view=windowsdesktop-7.0
  73. InvokePattern button6Invoke = (InvokePattern)btn6.GetCurrentPattern(InvokePattern.Pattern);
  74. //Invoke() 发送请求以激活控件并启动其单一、明确的操作。
  75. button6Invoke.Invoke();
  76. Condition conditionBtnPlus = new AndCondition(
  77. new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
  78. new PropertyCondition(AutomationElement.NameProperty, "加")
  79. );
  80. var btnPlus = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtnPlus);
  81. InvokePattern buttonPlusInvoke = (InvokePattern)btnPlus.GetCurrentPattern(InvokePattern.Pattern);
  82. buttonPlusInvoke.Invoke();
  83. }
  84. private static void InvokeButton(AutomationElement e)
  85. {
  86. InvokePattern Invoke = (InvokePattern)e.GetCurrentPattern(InvokePattern.Pattern);
  87. Invoke.Invoke();
  88. }
  89. private static void ClickCalculatorButton(AutomationElement calcFrame1, String name)
  90. {
  91. Condition conditionBtn = new AndCondition(
  92. new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
  93. new PropertyCondition(AutomationElement.NameProperty, name)
  94. );
  95. var btn = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn);
  96. // MessageBox.Show(btn.Current.Name);
  97. if (btn == null)
  98. {
  99. throw new Exception("找不到此" + name + "的按钮");
  100. }
  101. InvokeButton(btn);
  102. }
  103. private void button6_Click(object sender, EventArgs e)
  104. {
  105. AutomationElement desktop = AutomationElement.RootElement;
  106. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  107. new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));
  108. ClickCalculatorButton(calcFrame1, "三");
  109. ClickCalculatorButton(calcFrame1, "乘以");
  110. ClickCalculatorButton(calcFrame1, "五");
  111. ClickCalculatorButton(calcFrame1, "五");
  112. ClickCalculatorButton(calcFrame1, "等于");
  113. }
  114. [DllImport("user32.dll")]
  115. public static extern void SetCursorPos(int x, int y);
  116. [DllImport("user32.dll")]
  117. public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
  118. private void button7_Click(object sender, EventArgs e)
  119. {
  120. AutomationElement desktop = AutomationElement.RootElement;
  121. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  122. new PropertyCondition(AutomationElement.ClassNameProperty, "ApplicationFrameWindow"));
  123. Condition conditionBtn6 = new AndCondition(
  124. new PropertyCondition(AutomationElement.ClassNameProperty, "Button"),
  125. new PropertyCondition(AutomationElement.NameProperty, "六")
  126. );
  127. var btn6 = calcFrame1.FindFirst(TreeScope.Descendants, conditionBtn6);
  128. SetCursorPos((int)btn6.GetClickablePoint().X, (int)btn6.GetClickablePoint().Y);
  129. //mouse_event(0x0002 | 0x0004, 0, 0, 0, 0);
  130. mouse_event(0x0002, 0, 0, 0, 0); // 模拟鼠标左键按下
  131. mouse_event(0x0004, 0, 0, 0, 0); // 模拟鼠标左键弹起
  132. }
  133. private void button8_Click(object sender, EventArgs e)
  134. {
  135. AutomationElement desktop = AutomationElement.RootElement;
  136. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  137. new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
  138. Condition conditionEdit = new AndCondition(
  139. new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"), new PropertyCondition(AutomationElement.NameProperty, "文本编辑器"));
  140. AutomationElement txtEdit = calcFrame1.FindFirst(TreeScope.Descendants, conditionEdit);
  141. txtEdit.SetFocus();
  142. SendKeys.Send("追加123456789");
  143. }
  144. private const int WM_SETTEXT = 0x000C;
  145. [DllImport("user32.dll")]
  146. private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  147. [DllImport("User32.dll")]
  148. private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindows);
  149. [DllImport("User32.dll")]
  150. private static extern Int32 SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam);
  151. private void button9_Click(object sender, EventArgs e)
  152. {
  153. AutomationElement desktop = AutomationElement.RootElement;
  154. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  155. new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
  156. Condition conditionEdit = new AndCondition(
  157. new PropertyCondition(AutomationElement.ClassNameProperty, "Edit"), new PropertyCondition(AutomationElement.NameProperty, "文本编辑器"));
  158. AutomationElement txtEdit = calcFrame1.FindFirst(TreeScope.Descendants, conditionEdit);
  159. //.NET提供了一个结构体System.IntPtr专门用来代表句柄或指针。
  160. //句柄是对象的标识符,当调用这些API创建对象时,它们并不直接返回指向对象的指针,
  161. //而是会返回一个32位或64位的整数值,这个在进程或系统范围内唯一的整数值就是句柄(Handle),
  162. //随后程序再次访问对象,或者删除对象,都将句柄作为Windows API的参数来间接对这些对象进行操作。
  163. //句柄是一个结构体,简单的来说,它是指针的一个封装,是C#中指针的替代者
  164. //句柄链接:https://blog.csdn.net/sinat_40003796/article/details/127244155
  165. IntPtr hWnd = FindWindow("Notepad", null);
  166. if (!hWnd.Equals(IntPtr.Zero))
  167. {
  168. IntPtr edithWnd = FindWindowEx(hWnd, IntPtr.Zero, "Edit", null);
  169. if (!edithWnd.Equals(IntPtr.Zero))
  170. {
  171. SendMessage(edithWnd, WM_SETTEXT, IntPtr.Zero, new StringBuilder("重写123456789"));
  172. }
  173. }
  174. else
  175. {
  176. }
  177. }
  178. private void button10_Click(object sender, EventArgs e)
  179. {
  180. //点击后有列表的按钮不要当成点击事件
  181. AutomationElement desktop = AutomationElement.RootElement;
  182. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  183. new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
  184. Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, "编辑(E)");
  185. AutomationElement w2 = calcFrame1.FindFirst(TreeScope.Descendants, myCondition2);
  186. ExpandCollapsePattern ecp = (ExpandCollapsePattern)w2.GetCurrentPattern(ExpandCollapsePattern.Pattern);
  187. ecp.Expand();
  188. }
  189. private AutomationElement autoElementGet1(AutomationElement e, string s)
  190. {
  191. Condition myCondition1 = new PropertyCondition(AutomationElement.AutomationIdProperty, s);
  192. Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, s);
  193. Condition myCondition3 = new PropertyCondition(AutomationElement.AcceleratorKeyProperty, s);
  194. Condition myCondition4 = new PropertyCondition(AutomationElement.ClassNameProperty, s);
  195. Condition myCondition5 = new PropertyCondition(AutomationElement.AccessKeyProperty, s);
  196. Condition myCondition6 = new PropertyCondition(AutomationElement.LocalizedControlTypeProperty, s);
  197. Condition myCondition = new OrCondition(myCondition1, myCondition2, myCondition3, myCondition4, myCondition5,
  198. myCondition6);
  199. AutomationElementCollection myCollection = e.FindAll(TreeScope.Descendants, myCondition);
  200. return myCollection[0];
  201. }
  202. private void button11_Click(object sender, EventArgs e)
  203. {
  204. //随机元素获取
  205. AutomationElement desktop = AutomationElement.RootElement;
  206. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  207. new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
  208. AutomationElement filename = autoElementGet1(calcFrame1, "文件(F)");
  209. MessageBox.Show("Name:" + filename.Current.Name + ";ClassName=" + filename.Current.ClassName);
  210. }
  211. private void button12_Click(object sender, EventArgs e)
  212. {
  213. //遍历子控件
  214. AutomationElement desktop = AutomationElement.RootElement;
  215. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  216. new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
  217. Condition myCondition1 = new PropertyCondition(AutomationElement.AutomationIdProperty, "MenuBar");
  218. AutomationElement MenuBar = calcFrame1.FindFirst(TreeScope.Descendants, myCondition1);
  219. AutomationElementCollection MenuBarChildAll = MenuBar.FindAll(TreeScope.Children, Condition.TrueCondition);
  220. for (int i = 0; i < MenuBarChildAll.Count; i++)
  221. {
  222. AutomationElement MenuBarChild = MenuBarChildAll[i];
  223. MessageBox.Show("Name:" + MenuBarChild.Current.Name + ";ClassName=" + MenuBarChild.Current.ClassName + ";ControlType=" + MenuBarChild.Current.ControlType);
  224. }
  225. }
  226. private void button13_Click(object sender, EventArgs e)
  227. {
  228. processcalc = Process.Start(@"C:\Windows\System32\calc.exe");
  229. }
  230. private void button14_Click(object sender, EventArgs e)
  231. {
  232. processcalc.Kill();
  233. }
  234. private void button15_Click(object sender, EventArgs e)
  235. {
  236. //点击后有列表的按钮不要当成点击事件
  237. AutomationElement desktop = AutomationElement.RootElement;
  238. var calcFrame1 = desktop.FindFirst(TreeScope.Children,
  239. new PropertyCondition(AutomationElement.ClassNameProperty, "Notepad"));
  240. Condition myCondition1 = new PropertyCondition(AutomationElement.NameProperty, "文件(F)");
  241. AutomationElement w1 = calcFrame1.FindFirst(TreeScope.Descendants, myCondition1);
  242. ExpandCollapsePattern ecp = (ExpandCollapsePattern)w1.GetCurrentPattern(ExpandCollapsePattern.Pattern);
  243. ecp.Expand();
  244. Condition myCondition2 = new PropertyCondition(AutomationElement.NameProperty, "退出(X)");
  245. AutomationElementCollection myCollection = w1.FindAll(TreeScope.Descendants, myCondition2);
  246. AutomationElement w2 = myCollection[0];
  247. InvokePattern ipn = (InvokePattern)w2.GetCurrentPattern(InvokePattern.Pattern);
  248. ipn.Invoke();
  249. Thread.Sleep(500);
  250. AutomationElement savefile = calcFrame1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "保存(S)"));
  251. if (savefile != null)
  252. {
  253. InvokePattern savefilebutton = (InvokePattern)savefile.GetCurrentPattern(InvokePattern.Pattern);
  254. savefilebutton.Invoke();
  255. Thread.Sleep(500);
  256. AutomationElement Saveasform = calcFrame1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "另存为"));
  257. AutomationElement edit1 = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "1001"));
  258. ValuePattern vp = (ValuePattern)edit1.GetCurrentPattern(ValuePattern.Pattern);
  259. vp.SetValue("aaa.txt");
  260. AutomationElement savefilepath = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "保存(S)"));
  261. InvokePattern savefilepathbutton = (InvokePattern)savefilepath.GetCurrentPattern(InvokePattern.Pattern);
  262. savefilepathbutton.Invoke();
  263. Thread.Sleep(500);
  264. AutomationElement yesSaveasform = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "确认另存为"));
  265. AutomationElement issavefilepath = Saveasform.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "是(Y)"));
  266. if (issavefilepath != null) {
  267. InvokePattern issavefilepathbutton = (InvokePattern)issavefilepath.GetCurrentPattern(InvokePattern.Pattern);
  268. issavefilepathbutton.Invoke();
  269. }
  270. }
  271. }
  272. }
  273. }

各按钮的功能展示

打开记事本

关闭记事本

获取计算器窗体

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

 结果

获取控件属性

 结果

点击按钮

完成计算器计算

 鼠标点击按钮

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

 追加记事本内容

原始

运行

 重写记事本内容

展开按钮列表

随机获取元素方法

遍历记事本菜单栏

打开计算器

控件关闭计算器

 保存记事本

工程示例

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

参考

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/105122
推荐阅读
相关标签
  

闽ICP备14008679号