UIAutomation不会检索元素的子元素

Aug*_*ust 7 c# windows ui-automation microsoft-ui-automation

我可以看到具有特定自动化ID的元素在Inspect工具中有子项:

检查截图

但是当我尝试像这样检索它们时:

AutomationElement aPane = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.AutomationIdProperty, "8264"));
AutomationElementCollection theChildren = aPane.FindAll(TreeScope.Subtree, Condition.TrueCondition);
Run Code Online (Sandbox Code Playgroud)

aPane元件被正确地恢复,但theChildren元件是空的.出了什么问题?

Mik*_*ray 12

在极少数情况下,我发现Find*调用找不到所有自动化对象.我见过的唯一一致的情况是WPF TextBlock控制,当在数据模板中时,这些调用将找不到它.在这些情况下,您可以尝试RawViewWalker更接近Inspect在内部执行的操作.

public static IEnumerable<AutomationElement> FindInRawView(this AutomationElement root)
{
    TreeWalker rawViewWalker = TreeWalker.RawViewWalker;
    Queue<AutomationElement> queue = new Queue<AutomationElement>();
    queue.Enqueue(root);
    while (queue.Count > 0)
    {
       var element = queue.Dequeue();
       yield return element;

       var sibling = rawViewWalker.GetNextSibling(element);
       if (sibling != null)
       {
          queue.Enqueue(sibling);
       }

       var child = rawViewWalker.GetFirstChild(element);
       if (child != null)
       {
          queue.Enqueue(child);
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案是对的.RawViewWalker没有解决任何问题.我有同样的问题并尝试过,问题保持不变.未发现儿童的原因是微软在自动化服务器端的实施中存在严重缺陷.如果使用Win32应用程序,WPF应用程序和.NET Forms应用程序测试相同的代码,您会发现错误是不同的.虽然在WinForms应用程序中,有时不会返回相同的代码,但Win32应用程序中的代码完全相同.Microsoft使用Automation框架进行了非常糟糕的工作. (5认同)

Aug*_*ust 2

实际上,问题在于 Inspect.exe 是用非托管代码编写的,而我试图在托管代码中实现相同的结果。非托管代码返回的结果与托管版本略有不同(例如,托管代码将返回控制类型文档,其中非托管代码将返回我的应用程序中的编辑)。

虽然我花了一些时间来理解它,但非托管代码更快、更准确,因此也更可靠。

C# 的非托管 UI 自动化代码的一些示例可以在 Microsoft Windows UI 自动化博客中找到,例如

  • 托管和非托管确实有不同的实现。还有更好的管理实现:https://www.nuget.org/packages/UIAComWrapper/ (2认同)