Flaui使用说明

本文详细介绍了FlaUI库在自动化测试Windows应用程序时如何获取和操作窗体及元素。FlaUI是一个.NET库,用于Win32、WinForms、WPF和StoreApps的UI自动化,基于Microsoft的UIAutomation库。文章分别讲述了四种窗体获取模式以及通过XPath获取元素的推荐方法,并提供了元素操作的示例,如文本框、组合框、复选框和单选按钮等。

问题传送

目录

简介

一、获取窗体

1.ByMain

2.ByMainChild

3.ByAllTopLevel

4、ByAllDesktop

二、获取元素

1.通过Xpath获取 推荐使用

三、元素操作


简介

FlaUI 是一个 .NET 库,可帮助对 Windows 应用程序(Win32、WinForms、WPF、Store Apps 等)进行自动化 UI 测试。
它基于 Microsoft 的本机 UI 自动化库,因此是它们的包装器。
FlaUI 包装了 UI Automation 库中的几乎所有内容,但也提供了本机对象,以防有人有 FlaUI 尚未涵盖的特殊需求。
源代码网址:http://www.github.com/Roemer/FlaUI
FlaUI源代码文档:https://github.com/FlaUI/FlaUI/wiki

FlaUI官方介绍讲分两个版本

  • UIA2:原生 UI 自动化 API 的托管库
    • UIA2 是只管理的,这对 C# 来说很好,但它不支持更新的功能(如触摸),而且它也不能很好地与 WPF 一起工作,甚至更糟糕的是与 Windows 应用商店应用程序一起工作。
  • UIA3:原生 UI 自动化 API 的 Com 库
    • UIA3 是最新的,非常适合 WPF/Windows 商店应用程序,但不幸的是,它可能有一些 WinForms 应用程序的错误(请参阅常见问题解答),这些错误在 UIA2 中不存在。

尝试下来:winform界面 尽量用UIA2,其他用UIA3,并且同一APPDomain只能存在一个对象,也切换时需要重启。

一、获取窗体

获取窗体有时候最困难,你可能遇到且不限于:类名重复、类名变化、窗体名重复、窗体父子关系但是父窗体设置成MDI,甚至有的窗体实际上是个Panle等等诸如此类。

获取窗体分为四种模式:

       为什么要分为四种模式呢?写RPA脚本的时候要根据窗体的层级关系选择合适的代码,查找的执行效率和查询的范围有关,预设的范围越小,查询的效率越快。这几种模式下边会一一介绍。

        [Description("当前进程主窗体")]
        ByMain,
        [Description("当前进程主窗体的子窗体")]
        ByMainChild,
        [Description("当前进程所有弹出窗体")]
        ByAllTopLevel,
        [Description("当前桌面所有弹出窗体")]
        ByAllDesktop,

获取的条件:

 获取的条件也要根据实际情况进行选择,有些窗体类名一致、窗体名不同,有些类名窗体名都不同。值的注意的是XPath组件内部自己生成的类似xml结构的固定格式,执行效率很高,建议获取元素的时候使用。

       [Description("类名")]
        ClassName,
        [Description("窗体名")]
        Title,
        [Description("AutomationId")]
        AutomationId,
        [Description("XPath(窗体不可用)")]
        XPath,
        [Description("类名和窗体名")]
        ClassNameAndTitle,
        [Description("类名或窗体名")]
        ClassNameOrTitle,

1.ByMain

要捕获的窗体只有一个、或者有父子关系时的父窗体(模态框)。

注意:非模态框不能用此模式

 System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(processName);//获取进程
 var id = processes.First().Id;
 var app = FlaUI.Core.Application.Attach(id);
//new TimeSpan(1) 不能缺省 否则会假死
 var mainWindow = appl?.GetMainWindow(AutomationBase, new TimeSpan(1));

2.ByMainChild

要捕获的窗体是父子关系时的子窗体(模态框)

 System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(processName);//获取进程
 var id = processes.First().Id;
 var app = FlaUI.Core.Application.Attach(id);
//new TimeSpan(1) 不能缺省 否则会假死
 var mainWindow = appl?.GetMainWindow(AutomationBase, new TimeSpan(1));
 var property = model.WindowProperty;
 var controlType = model.ControlType;
 var frameworkType = model.FrameworkType;
 var className = model.ClassName;
 var name = model.Title;
 var automationId = model.AutomationId;
  mainWindows = FindWindowByAllChildren(mainWindow, property, controlType, frameworkType, className, name, automationId);
 private static AutomationElement[] FindWindowByAllChildren(AutomationElement windows,
            PropertyType property, ControlType controlType, FrameworkType frameworkType,
            string className, string name, string automationId)
        {
            AutomationElement[] mainWindows = null;
            switch (property)
            {
                case PropertyType.ClassName:
                    {
                        //桌面的直接子窗口
                        mainWindows = windows?.FindAllChildren(cf => cf.ByClassName(className).
                       And(cf.ByControlType(controlType).And(cf.ByFrameworkType(frameworkType))));
                        break;
                    }
                case PropertyType.Title:
                    {
                        //桌面的直接子窗口
                        mainWindows = windows?.FindAllChildren(cf => cf.ByName(name).
                       And(cf.ByControlType(controlType).And(cf.ByFrameworkType(frameworkType))));
                        break;
                    }
                case PropertyType.AutomationId:
                    {
                        //桌面的直接子窗口
                        mainWindows = windows?.FindAllChildren(cf => cf.ByAutomationId(automationId).
                       And(cf.ByControlType(controlType).And(cf.ByFrameworkType(frameworkType))));
                        break;
                    }
                case PropertyType.ClassNameAndTitle:
                    {
                        //桌面的直接子窗口
                        mainWindows = windows?.FindAllChildren(cf => cf.ByClassName(className).And(cf.ByName(name)).
                       And(cf.ByControlType(controlType).And(cf.ByFrameworkType(frameworkType))));
                        break;
                    }
                case PropertyType.ClassNameOrTitle:
                    {
                        //桌面的直接子窗口
                        mainWindows = windows?.FindAllChildren(cf => cf.ByClassName(className).Or(cf.ByName(name)).
                       And(cf.ByControlType(controlType).And(cf.ByFrameworkType(frameworkType))));
                        break;
    
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值