在powershell中使用Windows UI Automation进行UI自动化测试

来源:互联网 发布:剑灵人族大叔捏脸数据 编辑:程序博客网 时间:2024/05/13 04:14
在使用Windows UI Automation的时候,要查找某一UI元素,通常要先获取一个RootElement——桌面。其他所有的Element都是基于RootElement之上。该如何获取RootElement呢?

[Reflection.Assembly]::LoadWithPartialName("UIAutomationClient")
$rootElement = ([Windows.Automation.AutomationElement]::RootElement)


如果按照如上的方式加载Assembly,可以获得到RootElement,但是RootElement中的信息很不完整,甚至是严重的缺失,几乎不能正常使用
发生这种问题的原因是,UIAutoimation的API只能够在STA(Single-Thread Apartment)环境中运行,而powershell目前只能在MTA(Multi-Thread Apartment)环境中运行,而且不能够进行切换,导致运行时不兼容。有关STA和MTA可以参考MSDN中Apartment的定义或者STA和MTA杂谈
通常编写的.Net程序默认都是STA的,因此可以编写一个.Net的DLL获取RootElement,然后在powershell中使用,如下:

using System;
using System.Windows.Automation;
public static class AutomationHelper
{
public static object GetRootElement()
    {
        return System.Windows.Automation.AutomationElement.RootElement;
    }
}


然后利用Add-Type这个Cmdlet可以很方面将上述C#代码编译为库文件并加载到powershell环境中使用(不要忘记附加的ReferencedAssemblies):

$source = @'
using System;
using System.Windows.Automation;
public static class AutomationHelper
{
public static object GetRootElement()
    {
        return System.Windows.Automation.AutomationElement.RootElement;
    }
}
'@
Add-Type -TypeDefinition $source -ReferencedAssemblies 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\UIAutomationClient.dll'


这样,就已经将C#的源码编译为临时的DLL文件,并且以STA的方式加载到powershell环境中了。

当成功获得了我们需要的RootElement,我们就已经成功一半了,接下来的事情就是要通过各种条件使用UIAutomation的API来查找我们指定的UI元素了。以notepad为例子,如下:

$source = @'
using System;
using System.Windows.Automation;
public static class AutomationHelper
{
public static object GetRootElement()
    {
        return System.Windows.Automation.AutomationElement.RootElement;
    }
}
'@
Add-Type -TypeDefinition $source -ReferencedAssemblies 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\UIAutomationClient.dll'

[diagnostics.process]::start("notepad.exe")
start-sleep 1
$rootElement = [AutomationHelper]::GetRootElement()
$window = new-object System.Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ControlTypeProperty, [Windows.Automation.ControlType]::Window)
$windowtext = new-object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty), "Untitled - Notepad"
$window = new-object Windows.Automation.AndCondition ($window, $windowtext)
$windowElement = $rootElement.FindFirst("Children", $window)
# Get the menubar
$menuBar = new-object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::AutomationIdProperty), "MenuBar"
$menuBarElement = $windowElement.FindFirst("Children", $menuBar)
$itemOne = new-object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::AutomationIdProperty),"Item 1"
$itemOneElement = $menuBarElement.FindFirst("Children", $itemOne)
# Expand the File menu from the menubar
$itemOneElement.GetCurrentPattern([System.Windows.Automation.ExpandCollapsePattern]::Pattern).Expand()

步骤为先设置PropertyCondition,然后以要查找的根节点元素开始用FindFirst()查找第一次出现的或者用FindAll()返回所有符合给定的PropertyCondition的元素,"Children"这个参数的类型是System.Windows.Automation.TreeScope,具体含义可以查阅MSDN。

根据不同的PropertyCondition组合,我们可以封装适用的Powershell UI Automation API,例如:GetElementById(),GetTextElementByName(),ClickButtonElementById()等等

 

还请参考使用 Windows PowerShell 实现 Web UI 自动化

原创粉丝点击