使用UI Automation实现自动化测试--5 (Winfrom和WPF中弹出和关闭对话框的不同处理方式)...

在使用UI AutomationWinformWPF的程序测试中发现有一些不同的地方,而这些不同来自于WinformWPF的处理机制不同。下面我们通过一个简单的实例来加以说明:

实例描述

我们使用InvokePattern来点击按钮弹出一个对话框,然后点击对话框中的“确定”按钮关闭对话框。

两种方式对比

首先我们使用如下代码来针对WinfomWPF分别进行测试:

ContractedBlock.gif ExpandedBlockStart.gif Code
 1public static void ClickButtonById(int processId, string buttonId)
 2ExpandedBlockStart.gifContractedBlock.gif{
 3    AutomationElement element = FindElementById(processId, buttonId);
 4    if (element == null)
 5ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 6        throw new NullReferenceException(string.Format("Element with AutomationId '{0}' can not be find.", element.Current.Name));
 7    }

 8    InvokePattern currentPattern = GetInvokePattern(element);
 9    currentPattern.Invoke();
10}

         上面的代码主要是用来点击按钮,我们的目的是点击按钮弹出MessageBox,然后点击MessageBox中的“OK”按钮关闭此对话框。

通过测试结果发现,上面的代码在WPF程序中完全可以通过,但是在Winform程序中,点击按钮弹出对话框之后发生阻塞现象,导致程序无法向下执行,所以我们通过如上代码视图点击MessageBox中的按钮来关闭此MessageBox将不可能实现,原因就在于Winform中的MessageBox弹出后就会出现阻塞现象,而WPF中使用了另一种处理方式(对此笔者解释的不够深刻,欢迎广大高手帮忙指正, 另外,此问题在Windows 7操作系统上面不会呈现,也可能与操作系统中API对UI Automation的支持有关)。

解决方案

     那么我们通过什么方式来解决此问题呢?很多人会想到多线程,但是我们也可以通过发送异步消息来达到相应的效果。下面我们就通过多线程和发送异步消息的方式来方式来点击WinformMessageBox中的“OK”按钮,此方法同样可以点击WPFMessageBox中的按钮达到关闭对话框的效果。

1.       多线程的方式

ContractedBlock.gif ExpandedBlockStart.gif Code
 1public static void ClickButtonById(int processId, string buttonId)
 2ExpandedBlockStart.gifContractedBlock.gif{
 3    AutomationElement element = FindElementById(processId, buttonId);
 4
 5    if (element == null)
 6ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 7        throw new NullReferenceException(string.Format("Element with AutomationId '{0}' can not be find.", element.Current.AutomationId));
 8    }

 9
10    ThreadStart start2 = null;
11
12    if (start2 == null)
13ExpandedSubBlockStart.gifContractedSubBlock.gif    {
14        start2 = delegate
15ExpandedSubBlockStart.gifContractedSubBlock.gif        {
16            object obj2;
17            if (!element.TryGetCurrentPattern(InvokePattern.Pattern, out obj2))
18ExpandedSubBlockStart.gifContractedSubBlock.gif            {
19                throw new Exception(string.Format("Button element with AutomationId '{0}' does not support the InvokePattern.", element.Current.AutomationId));
20            }

21            (obj2 as InvokePattern).Invoke();
22        }
;
23    }

24    ThreadStart start = start2;
25    new Thread(start).Start();
26    Thread.Sleep(0xbb8);
27}

 

1.       发送异步消息的方式

ContractedBlock.gif ExpandedBlockStart.gif Code
 1[DllImport("user32.dll", CharSet = CharSet.Auto)]
 2private static extern IntPtr PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
 3[DllImport("user32.dll", CharSet = CharSet.Auto)]
 4private static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
 5
 6public static void ClickButtonById(this Tester tester, int processId, string buttonId)
 7ExpandedBlockStart.gifContractedBlock.gif{
 8    AutomationElement element = FindElementById(processId, buttonId);
 9    if (element == null)
10ExpandedSubBlockStart.gifContractedSubBlock.gif    {
11        throw new NullReferenceException(string.Format("Element with AutomationId '{0}' can not be find.", element.Current.AutomationId));
12    }

13
14    IntPtr nativeWindowHandle = (IntPtr)element.Current.NativeWindowHandle;
15    if (nativeWindowHandle != IntPtr.Zero)
16ExpandedSubBlockStart.gifContractedSubBlock.gif    {
17        HandleRef hWnd = new HandleRef(nativeWindowHandle, nativeWindowHandle);
18        PostMessage(hWnd, 0xf5, IntPtr.Zero, IntPtr.Zero);
19    }

20    }

21}

 

相关FindWindow和FindElement代码:

ContractedBlock.gif ExpandedBlockStart.gif Code
 1ExpandedBlockStart.gifContractedBlock.gif/**//// <summary>
 2/// Get the automation elemention of current form.
 3/// </summary>
 4/// <param name="processId">Process Id</param>
 5/// <returns>Target element</returns>

 6public static AutomationElement FindWindowByProcessId(int processId)
 7ExpandedBlockStart.gifContractedBlock.gif{
 8    AutomationElement targetWindow = null;
 9    int count = 0;
10    try
11ExpandedSubBlockStart.gifContractedSubBlock.gif    {
12        Process p = Process.GetProcessById(processId);
13        targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
14        return targetWindow;
15    }

16    catch (Exception ex)
17ExpandedSubBlockStart.gifContractedSubBlock.gif    {
18        count++;
19        StringBuilder sb = new StringBuilder();
20        string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
21        if (count > 5)
22ExpandedSubBlockStart.gifContractedSubBlock.gif        {
23            throw new InvalidProgramException(message, ex);
24        }

25        else
26ExpandedSubBlockStart.gifContractedSubBlock.gif        {
27            return FindWindowByProcessId(processId);
28        }

29    }

30}

31
32
33ExpandedBlockStart.gifContractedBlock.gif/**//// <summary>
34/// Get the automation element by automation Id.
35/// </summary>
36/// <param name="windowName">Window name</param>
37/// <param name="automationId">Control automation Id</param>
38/// <returns>Automatin element searched by automation Id</returns>

39public static AutomationElement FindElementById(int processId, string automationId)
40ExpandedBlockStart.gifContractedBlock.gif{
41    AutomationElement aeForm = FindWindowByProcessId(processId);
42    AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
43    new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
44    return tarFindElement;
45}

 

          本节主要针对在非Window 7操作系统上面出现的有关WPFWinform中的MessageBox关闭问题作了简单的探讨。

 

转载于:https://www.cnblogs.com/kangyi/archive/2009/10/27/1590500.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值