为什么UISpy可以看到的控件 FindFirst却找不到

来源:互联网 发布:软件推荐 编辑:程序博客网 时间:2024/04/29 21:53

       如果你是通过Accessibility来做Windows下的界面自动化测试,即用UI Automation(UIA)这套框架来做的,那估计你应该用过UISpy这个程序(如果你还不知道UISpy这个程序可以点击此处了解http://technet.microsoft.com/zh-cn/library/ms727247)

       如果你想在自己的程序中查找其它程序的界面上的按钮等控件,可以使用AutomationElement.FindFirst或TreeWalker类来实现,不知你是否遇到过在UISpy中可以看到某个控件但用AutomationElement.FindFirst或TreeWalker却怎么也无法找到的情况。以下是研究了很久才找到的解决方案:

       需要用异步委托,来封装AutomationElement.FindFirst,否则直接调用此函数返回的结果会和UISpy看到的有差别,后来又试了一下,其实直接新建一个线程并启动,最后等线程结束后也可以看到期望的结果。异步委托应该也是通过多线程来实现的,看来问题关键是AutomationElement.FindFirst或TreeWalker等UIA的操作需要在单独的线程中来完成,注意以上使用UIA的程序和被测程序并不是同一个,所以为什么需要使用单独的线程我也不是很清楚。

PS:异步委托代码所在类的父类中不能含有ServicedComponent,否则结果也会和UISpy不同

      另外还有两点需要注意:

      1.发现部分机器上UISpy看到的结果和我的机器有差别(会有节点丢失的情况),这时直接调AutomationElement.FindFirst的结果反而可以找到“丢失的”节点。

      2.如果只调用一次FindFirst在某些特殊情况下还是会出现找不到控件的情况,但调用第二次就可以找到了,。。。UIA的bug真多啊



以下附上可以解决上述几个问题的封装了AutomationElement的类

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace UITester{    using System.Windows.Automation;    /// <summary>    /// 扩展AutomationElement的功能 当前仅限于FindFirst    /// </summary>    public class myAutomationElementEx    {        private AutomationElement parent_element = null;        private AutomationElement find_element = null;        private TreeScope _findScope = TreeScope.Descendants;        private Condition _find_condition = null;        private delegate void FindElementDelegate();        private FindElementDelegate delegate2 = null;        public myAutomationElementEx()        {            delegate2 = new FindElementDelegate(FindFirst);        }        /// <summary>        /// 扩展AutomationElement的FindFirst        /// </summary>        /// <param name="start"></param>        /// <param name="findScope"></param>        /// <param name="find_condition"></param>        /// <returns></returns>        public AutomationElement FindFirst(AutomationElement start, TreeScope findScope, Condition find_condition)        {            parent_element = start;            _findScope = findScope;            find_element = null;            _find_condition = find_condition;                        //必须先用普通方式查找 否则在部分机器上会有找不到控件的情况 在这类机器上UISpy确实看不到部分控件 但用普通方式却可以找到            find_element = parent_element.FindFirst(_findScope, _find_condition);            if (null == find_element)            {                //部分控件找第二次才能找到                find_element = parent_element.FindFirst(_findScope, _find_condition);            }            if (null != find_element)            {                return find_element;            }            //不用这种方式的话 在第一次生成的窗体内(如对话框)搜到的控件会比实际的少            IAsyncResult asyncResult = delegate2.BeginInvoke(null, null);            delegate2.EndInvoke(asyncResult);            return find_element;        }        private void FindFirst()        {            find_element = parent_element.FindFirst(_findScope, _find_condition);        }    }}




原创粉丝点击