使用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
相关产品推荐
相关产品推荐

