zoukankan      html  css  js  c++  java
  • .NET自动化测试手记(3) 查看当前系统安装的更新

    这篇主要通过点击窗体按钮、监听窗体和控件的事件实现读取当前系统安装的更新。需要用到UISpy.exe。

    主要操作步骤如下:

    1. 运行命令打开"Programs and Features"窗体,同时监听窗体打开的事件
    2. 点击"View installed updates"按钮,跳转到"Installed Updates"窗口,同时监听窗体名字改变的事件
    3. 获取页面加载的进度条并读取进度,需要监听进度条进度发生改变的事件
    4. 获取承载所有更新项的datagrid
    5. 遍历所有更新项并执行操作

    以下是需要调用到的功能,先在这里列出来:

    获取给定控件里有特定名字的子控件
              public static AutomationElement FindControl(AutomationElement ele, ControlType type, string name)
    {
    if (ele==null)
    {
    return null;
    }
    PropertyCondition nameProperty = new PropertyCondition(AutomationElement.NameProperty, name);
    PropertyCondition typeProperty = new PropertyCondition(AutomationElement.ControlTypeProperty, type);
    AndCondition andCondition = new AndCondition(nameProperty, typeProperty);

    return ele.FindFirst(TreeScope.Subtree, andCondition);
    }
    获取给定空间里有特定属性的子控件
              public static AutomationElement FindControlByType(AutomationElement ele, ControlType type)
    {
    if (ele==null)
    {
    return null;
    }
    PropertyCondition typeProperty = new PropertyCondition(AutomationElement.ControlTypeProperty, type);

    return ele.FindFirst(TreeScope.Descendants, typeProperty);
    }
    获取有特定名字的窗体
              public static AutomationElement GetWindowByName(AutomationElement parent, string name)
    {
    if (parent == null)
    {
    throw new Exception("Parent element is null!");
    }

    PropertyCondition nameProperty = new PropertyCondition(AutomationElement.NameProperty, name);
    PropertyCondition typeProperty = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window);
    AndCondition andCondition = new AndCondition(nameProperty, typeProperty);

    return parent.FindFirst(TreeScope.Descendants | TreeScope.Element, andCondition);
    }

    下面进入正题:

    1. 运行命令打开"Programs and Features"窗体,同时监听窗体打开的事件

    首先需要声明一个AutomationEventHandler,如下:

    static AutomationEventHandler aeHandler = new AutomationEventHandler(OnProgramsWindowOpen);  //监听“Programs and Features”窗体打开的事件

     打开窗体并监听:

    运行命令打开"Programs and Features"窗体,同时开始监听
        public void Run()
        { 
                //添加AutomationEventHandler,监听"Programs and Features"的打开事件
    Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Subtree, aeHandler);

    //打开"Programs and Features"
    Process.Start("control", “appwiz.cpl”).WaitForExit();
        }

    2. 点击"View installed updates"按钮,跳转到"Installed Updates"窗口,同时监听窗体名字改变的事件

    首先,定义EventHandler

    static AutomationPropertyChangedEventHandler propChangedHander = new AutomationPropertyChangedEventHandler(OnNameChanged);  //监听窗体名字变化
    

    当aeHandler监听到事件的时候会进入"OnProgramsWindowOpen”方法:

    获取并点击"View installed updates"超链接
              public static void OnProgramsWindowOpen(object sender,AutomationEventArgs args)
    {
    //获取窗体
    AutomationElement proWindow = sender as AutomationElement;
    //获取“View installed updates”超链接
    AutomationElement hyperViewUpdates = FindControl(proWindow, ControlType.Hyperlink, "View installed updates");

    if (hyperViewUpdates!=null)
    {
    //添加AutomationPropertyChangedEventHandler,监听窗体名字的变化
    Automation.AddAutomationPropertyChangedEventHandler(proWindow, TreeScope.Subtree, propChangedHander, AutomationElementIdentifiers.NameProperty);
    //点击超链接
    InvokePattern invoke = (InvokePattern)hyperViewUpdates.GetCurrentPattern(InvokePattern.Pattern);
    invoke.Invoke();
    }
    }

    3. 获取页面加载的进度条并读取进度,需要监听进度条进度发生改变的事件

    声明EventHandler监听进度条的进度: 

    static AutomationPropertyChangedEventHandler proBarChangedHander = new AutomationPropertyChangedEventHandler(OnValueChanged);

    当窗体名称发生改变时开始监听进度条的进度:

    查看窗体名称并监听进度条进度
              public static void OnNameChanged(object sender, AutomationPropertyChangedEventArgs args)
    {
    //获取当前窗体
    AutomationElement ele = sender as AutomationElement;

    if (ele.Current.Name == "Installed Updates")
    {
    //移除所有EventHandler,以免对后面的handler产生影响。如果没有影响也可以不加这句
    Automation.RemoveAllEventHandlers();
    Console.WriteLine("Name switched, is {0}", ele.Current.Name);
    //等待页面加载进度完成
    WaitForLoaded();
    }
    else
    {
    Console.WriteLine("Name is {0}", ele.Current.Name);
    }
    }
    监听进度条加载进度
          public static bool IsContinueRefresh = true;
              private static void WaitForLoaded()
    {
    //由于窗体名字改变了,需要重新获取名为"Installed Updates"窗体
    AutomationElement proWindow = GetWindowByName(AutomationElement.RootElement, "Installed Updates");
    Console.WriteLine("Class Name: {0}", proWindow.Current.ControlType.LocalizedControlType);
    Console.WriteLine("Handler:{0}", proWindow.Current.NativeWindowHandle.ToString());
    if (proWindow != null)
    {
    //获取进度条
    AutomationElement progressBar = FindControlByType(proWindow, ControlType.ProgressBar);

    //获取刷新按钮,有的时候可能需要重复刷新进度条才会有明显的(可以监听到的)进度变化。
    AutomationElement refreshButton = FindControl(proWindow, ControlType.Button, "Refresh \"Installed Updates\"");
    InvokePattern invoke = (InvokePattern)refreshButton.GetCurrentPattern(InvokePattern.Pattern);

    //添加监听事件
    Automation.AddAutomationPropertyChangedEventHandler(progressBar, TreeScope.Element, proBarChangedHander, RangeValuePattern.ValueProperty);

    //不停刷新窗体,直到监听到进度条的变化
    while (IsContinueRefresh)
    {
    Console.WriteLine(refreshButton.Current.Name);
    Thread.Sleep(1000);
    if (IsContinueRefresh)
    {
    try
    {
    Console.WriteLine("Refresh...");
    invoke.Invoke();
    }
    catch
    {
    Console.WriteLine("Exception, break...");
    break;
    }
    }
    else
    {
    break;
    }
    }
    }
    }

    4. 读取进度,当进度为100%的时候遍历所有更新项并读取各项的名字

    获取更新项并执行操作
              public static void OnValueChanged(object sender, AutomationPropertyChangedEventArgs args)
    {
    // 停止刷新窗体
    IsContinueRefresh = false;

    //实例化进度条
    AutomationElement pb = sender as AutomationElement;
    //获取进度条的RangeValuePattern, 方便后面读取进度
    RangeValuePattern rangePb = (RangeValuePattern)pb.GetCurrentPattern(RangeValuePattern.Pattern);
    double percent=rangePb.Current.Value;

    if ( percent == 100)
    {
    //移除所有的EventHandler,节省系统资源,同时也避免EventHandler之间的影响
      Automation.RemoveAllEventHandlers();

    //逐级获取控件,直到找到对应的更新列表
      AutomationElement proWindow = GetWindowByName(AutomationElement.RootElement, "Installed Updates"); //获取“Installed Updates”窗体元素
      AutomationElement datagrid = FindControl(proWindow, ControlType.DataGrid, "Folder View"); //获取更新列表元素
    AutomationElementCollection dataItems = datagrid.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.DataItem)); //获取所有更新元素的集合

    //遍历所有更新元素并执行操作
    foreach (AutomationElement item in dataItems)
    {
    //将元素滚动到屏幕显示范围之内
    ScrollItemPattern scrollPattern = (ScrollItemPattern)item.GetCurrentPattern(ScrollItemPattern.Pattern);
    scrollPattern.ScrollIntoView();

    //在控制台中显示元素的值
    ValuePattern value = (ValuePattern)item.GetCurrentPattern(ValuePattern.Pattern);
    Console.WriteLine(value.Current.Value);
    }
    }
    else
    {
    //显示进度
    ShowPercentage(percent);
    }
    }
    模拟进度条
              private static void ShowPercentage(double percent)
    {
    int top = Console.CursorTop;
    Console.WriteLine("Current progress is {0}%", percent.ToString());
    Console.CursorTop = top;
    }

    到这里,所要实现的操作就已经完成了。

    关于如何确定要监听哪些事件,可以借助UISpy.exe,具体操作如下(以监听进度条进度为例):

    首先,打开控制面板,进入到"Installed Updates"页

    然后打开UISpy.exe,找到(如果显示的元素没有这么多,可以把窗体调到最前面,然后刷新UISpy.exe)

    找到进度条

    点击菜单栏监听按钮开始监听(建议取消监听会引起Exception的事件,可以在右边那个按钮"Configure Events"里面设置)

    刷新窗体,并观察UISpy.exe “Output”里的变化,可以发现类似下面的文字。这时就可以确定该监听哪些事件,并从哪些属性里面观察变化了。

    Property Change Event
    Time Stamp : 2/18/2012 4:24:42 PM
    Element : "progress bar" ""
    Property : RangeValuePatternIdentifiers.ValueProperty
    New Value : 99
    Old Value : null
    
    Property Change Event
    Time Stamp : 2/18/2012 4:24:44 PM
    Element : "progress bar" ""
    Property : RangeValuePatternIdentifiers.ValueProperty
    New Value : 100
    Old Value : null
    
  • 相关阅读:
    计算机网络——简单的端口扫描器
    Java课程设计——模拟行星运动
    H5 自定义数据属性
    实时获取网络状态
    Web 存储
    关于节流阀的理解
    DOM元素尺寸和位置
    H5选择符api
    HTML和XHTML的区别
    HTML的发展史
  • 原文地址:https://www.cnblogs.com/silverbullet11/p/2357232.html
Copyright © 2011-2022 走看看