UIAutomationのサンプル

昨日書いたもののソースを掲載。
クラス名はUIWindowでない方が良いかな。

$source = @"
using System;
using System.Windows.Automation;
using System.Threading;

public class UIWindow
{
    private const int _moment = 100;
    private AutomationElement _ae;
    private AutomationProperty _ap = AutomationElement.AutomationIdProperty;

    public AutomationElement Element
    {
        get { return _ae; }
    }
    public AutomationProperty Property
    {
        get { return _ap; }
        set { _ap = value; }
    }

    public UIWindow()
    {
        _ae = AutomationElement.RootElement;
    }
    public UIWindow(string name)
    {
        _ae = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, name));
    }
    public UIWindow(AutomationElement ae, AutomationProperty ap)
    {
        _ae = ae;
        _ap = ap;
    }

    public UIWindow FindFirst(TreeScope ts, string name)
    {
        AutomationElement ae = _ae.FindFirst(ts, new PropertyCondition(_ap, name));
        return new UIWindow(ae, _ap);
    }
    public UIWindow FindFirst(string name)
    {
        return FindFirst(TreeScope.Descendants, name);
    }

    public UIWindow FindFirstHave(string className, string name)
    {
        UIWindow ret = null, sub = null;
        AutomationElementCollection aes = _ae.FindAll(TreeScope.Children, Condition.TrueCondition);
        foreach(AutomationElement ae in aes)
        {
            if (className.Equals(ae.GetCurrentPropertyValue(AutomationElement.ClassNameProperty)))
            {
                sub = new UIWindow(ae, _ap);
                sub = sub.FindFirstHave(className, name);
                if (sub != null)
                {
                    if (className.Equals(sub.Element.GetCurrentPropertyValue(AutomationElement.ClassNameProperty)))
                    {
                        ret = sub;
                    }
                    else
                    {
                        ret = new UIWindow(ae, _ap);
                    }
                    break;
                }
            }
            else if (name.Equals(ae.GetCurrentPropertyValue(_ap)))
            {
                ret = new UIWindow(ae, _ap);
                break;
            }
            else
            {
                sub = new UIWindow(ae, _ap);
                sub = sub.FindFirstHave(className, name);
                if (sub != null && className.Equals(sub.Element.GetCurrentPropertyValue(AutomationElement.ClassNameProperty)))
                {
                    ret = sub;
                    break;
                }
            }
        }
        return ret;
    }

    public bool Invoke()
    {
        bool ret = false;
        InvokePattern iv = _ae.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
        if (iv != null)
        {
            try
            {
                iv.Invoke();
                ret = true;
            }
            catch (ElementNotEnabledException e)
            {
                System.Diagnostics.Trace.Write(DateTime.Now);
                System.Diagnostics.Trace.WriteLine(e);
                ret = false;
            }
        }
        return ret;
    }
    public bool InvokeWaitEnable()
    {
        bool ret = WaitEnable();
        ret = Invoke();
        if (!ret)
        {
            // retry once
            Thread.Sleep(_moment * 10);
            ret = Invoke();
        }
        return ret;
    }

    public bool WaitEnable()
    {
        bool ret = false;
        object val = _ae.GetCurrentPropertyValue(AutomationElement.IsEnabledProperty);
        if (val != null)
        {
            while (false.Equals(val))
            {
                Thread.Sleep(_moment);
                val = _ae.GetCurrentPropertyValue(AutomationElement.IsEnabledProperty);
            }
            ret = true;
        }
        return ret;
    }

    public UIWindow WaitGet(bool child, string className, string name)
    {
        UIWindow ret = null;
        while (ret == null)
        {
            Thread.Sleep(_moment);
            if (child)
            {
                ret = FindFirstHave(className, name);
            }
            else
            {
                ret = FindFirst(name);
            }
        }
        return ret;
    }
}
"@
Add-Type -Language CSharp -TypeDefinition $source -ReferencedAssemblies ("UIAutomationClient", "UIAutomationTypes")
#([AppDomain]::CurrentDomain).GetAssemblies() | Out-Gridview

# メモ帳が起動している想定
# メモ帳を取得
$aec = New-Object UIWindow "無題 - メモ帳"

# バージョンを表示してOK
$aec.Property = [System.Windows.Automation.AutomationElement]::NameProperty
$aeh = $aec.FindFirst("ヘルプ(H)")
$aehe = $aeh.Element.GetCurrentPattern([System.Windows.Automation.ExpandCollapsePattern]::Pattern)
$aehe.Expand()
[System.Threading.Thread]::Sleep(100)
$aev = $aeh.FindFirst("バージョン情報(A)")
$aev.Invoke()
[System.Threading.Thread]::Sleep(2000)
$aeo = $aec.FindFirst("OK")
$aeo.Invoke()
[System.Threading.Thread]::Sleep(2000)

# TextPatternでは、テキストの挿入が今のところできない、、、
# SendInputの出番か!
# Win32APIをコールすべきな気がする。

# 終了
$aecw = $aec.Element.GetCurrentPattern([System.Windows.Automation.WindowPattern]::Pattern)
$aecw.Close()