zoukankan      html  css  js  c++  java
  • UIA 抛出COMException的解决方案

     

    Introducation

        在基于UI Automation平台的软件UI 自动化测试中,找控件的过程中有时候会出现如下异常:

    System.Runtime.InteropServices.COMException (0x80042002): Exception from HRESULT: 0x80042002

       at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)

       at MS.Internal.Automation.UiaCoreApi.CheckError(Int32 hr)

       at MS.Internal.Automation.UiaCoreApi.UiaFind(SafeNodeHandle hnode, UiaFindParams findParams, Condition findCondition, UiaCacheRequest request)

       at System.Windows.Automation.AutomationElement.Find(TreeScope scope, Condition condition, UiaCacheRequest request, Boolean findFirst, BackgroundWorker worker)

       at System.Windows.Automation.AutomationElement.FindFirst(TreeScope scope, Condition condition)

       --- End of inner exception stack trace ---

     

     

        通过在网上查找相关的资料,得知抛出COMException的原因是使用了非托管资源,在程序运行中GC无法自动回收相应的垃圾,进而导致此异常出现。

    Solution

     

    注:测试如下方法需要引入如下命名空间

    using System.Windows.Automation;

    using System.Runtime.InteropServices;

     

         如下代码为通过window name来查找window窗体的AutomationElement对象:

    /// <summary>

    /// Find target window by window name.

    /// </summary>

    /// <param name="windowName">Window name</param>

    /// <returns>Return target window element</returns>

    public static AutomationElement FindWindowByWindowName(string windowName)

    {

        AutomationElement targetWindow = null;

        int count = 0;

        try

        {

            targetWindow = AutomationElement.FromHandle(WindowPtr(windowName));

            return targetWindow;

        }

        catch (Exception)

        {

            Console.WriteLine("Try #" + count + 1 + " to find the target element");

            count++;

            if (count > 10)

            {

                throw new COMException ("Target window is not existing ,please run the program and  try it again");

            }

            GC.Collect();

            Thread.Sleep(3000);

            return FindWindowByWindowName(windowName);

        }

    }

     

    #region FindWindow Handing

    /// <summary>

    /// Find window with win32 API

    /// </summary>

    /// <param name="lpClassName">Class name</param>

    /// <param name="lpWindowName">WindowName</param>

    /// <returns></returns>

    [DllImport("USER32.DLL")]

    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    /// <summary>

    /// Find window IntPtr

    /// </summary>

    /// <param name="windowName">Application WindowName</param>

    private static IntPtr WindowPtr(string windowName)

    {

        IntPtr intPtr = FindWindow(null, windowName);

        return intPtr;

    }

    #endregion

     

        在上面的方法中,我们通过USER32.DLL中的FindWindow函数还获取对应窗体的IntPtr类型的对象,在FindWindowByWindowName方法中通过捕获COMException来循环调用此方法,一旦捕获到此异常,使用GC.Collect();来强制进行垃圾回收,是非托管资源被释放,这样在循环执行此方法时将不会应为内存错误而导致无法继续执行。经过测试发现,此种解决方案虽然不是最好的方法,但确实可以解燃眉之急。

    Reference

    http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/13004a05-8fa8-4b9c-b1f5-eff469f32235

    http://msdn.microsoft.com/zh-cn/library/s5zscb2d(VS.80).aspx

     

  • 相关阅读:
    shell命令执行过程
    shell中的引用
    ansible小结
    centos自动化安装镜像制作
    centos kickstart
    centos内核引导参数
    C# .NET 遍历Json 形成键值对
    强大的Winform Chart图表控件使用说明
    C#实现转换十六进制
    C# 批量登陆远程目录
  • 原文地址:https://www.cnblogs.com/kangyi/p/1622855.html
Copyright © 2011-2022 走看看