You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Interop.UIAutomationClient无法找到子菜单项的问题

问题:使用C# Interop.UIAutomationClient与.NET 8.0无法找到展开后的子菜单项

我之前在其他框架中见过类似问题的解答,但均未涉及C#、Interop.UIAutomationClient与.NET 8.0的场景。常见解决方案是查找子菜单项前先展开菜单,我已按此操作——因代码从使用AutomationElement的.NET Windows应用迁移至需用COM对象实现自动化的控制台应用,我编写了两个类:

1. 封装元素模式的WindowElement类

public class WindowElement
{
    private IUIAutomationElement? element;

    public WindowElement(IUIAutomationElement element) 
    { 
        this.element = element;
    }

    public WindowElement()
    {
    }

    public bool IsValid()
    {
        return element != null;
    }

    public IUIAutomationElement GetElement() 
    {
        return element;
    }

    public bool Expand()
    {
        if (element != null)
        {
            IUIAutomationExpandCollapsePattern pattern = element.GetCurrentPattern(WindowAutomation.UIA_ExpandCollapsePatternId);
            pattern.Expand();
            return pattern.CurrentExpandCollapseState == ExpandCollapseState.ExpandCollapseState_Expanded;
        }
        return false;
    }

    public bool Invoke()
    {
        if (element != null)
        {
            IUIAutomationInvokePattern pattern = element.GetCurrentPattern(WindowAutomation.UIA_InvokePatternId);
            pattern.Invoke();
            return true;
        }
        return false;
    }

    public bool Select()
    {
        if (element != null)
        {
            IUIAutomationSelectionItemPattern pattern = element.GetCurrentPattern(WindowAutomation.UIA_SelectionItemPatternId);
            pattern.Select();
            return true;
        }
        return false;
    }
}

2. 用于查找元素的WindowAutomation类

public class WindowAutomation
{
    private CUIAutomation8 uia = new CUIAutomation8();

    public WindowElement FindProcessNameElement(string processName)
    {
        IUIAutomationElement root = uia.GetRootElement();
        IUIAutomationElementArray children = root.FindAll(TreeScope.TreeScope_Children, uia.CreateTrueCondition());
        for (int i = 0; i < children.Length; i++)
        {
            IUIAutomationElement child = children.GetElement(i);
            string childName = child.CurrentName;
            if (childName.StartsWith(processName))
            {
                return new WindowElement(child);
            }
        }
        return new WindowElement();
    }

    public WindowElement FindMenuBarItem(WindowElement appElement, string itemName) 
    {
        if (appElement.IsValid())
        {
            IUIAutomationElementArray items = appElement.GetElement().FindAll(TreeScope.TreeScope_Children, uia.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_MenuBarControlTypeId));
            if (items.Length > 0)
            {
                items = items.GetElement(0).FindAll(TreeScope.TreeScope_Children, uia.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_MenuItemControlTypeId));
                for (int i = 0; i < items.Length; i++)
                {
                    IUIAutomationElement item = items.GetElement(i);
                    if (item.CurrentName == itemName)
                    {
                        return new WindowElement(item);
                    }
                }
            }
        }
        return new WindowElement();
    }

    public WindowElement FindSubmenuItem(WindowElement menuItem, string subitemName)
    {
        if (menuItem.IsValid())
        {
            menuItem.Expand();
            IUIAutomationElementArray items = menuItem.GetElement().FindAll(TreeScope.TreeScope_Descendants, uia.CreatePropertyCondition(UIA_ControlTypePropertyId, UIA_MenuItemControlTypeId));
            if (items.Length > 0)
            {
                for (int i = 0; i < items.Length; i++)
                {
                    IUIAutomationElement item = items.GetElement(i);
                    string name = item.CurrentName;
                    if (item.CurrentName == subitemName)
                    {
                        return new WindowElement(item);
                    }
                }
            }
        }
        return new WindowElement();
    }
}

执行代码时,我能看到菜单成功展开,但始终无法找到子菜单项,调用Invoke()无任何反应。我已尝试使用TreeScope_Descendants,仍未解决问题:

WindowElement app = ui.FindProcessNameElement("gMotor2 MAS");
WindowElement fileMenu = ui.FindMenuBarItem(app, "File");
if (fileMenu.Expand())
{
   Console.WriteLine("Expanded file menu");
}
WindowElement exitItem = ui.FindSubmenuItem(fileMenu, "Exit");
exitItem.Invoke();

预期Invoke()能退出应用,但实际无效果。

内容的提问来源于stack exchange,提问作者Tom Hansen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 05:43:13