9

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

检查屏幕截图

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

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

aPane元素被正确检索,但元素theChildren为空。任何想法出了什么问题?

4

6 回答 6

14

在极少数情况下,我发现Find*调用找不到所有自动化对象。我见过的唯一一致的情况是 WPFTextBlock控件在数据模板中时不会被这些调用找到。在这些情况下,您可以尝试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);
       }
    }
}
于 2013-01-06T22:45:45.927 回答
2

答案有点晚,但我想更正此处选择的答案。是的,VS 提供的 COM 包装器确实可能使用不同的 UIAutomationClient.dll,并且在调用 UIAutomation 方法时使用本机代码与托管代码会有所不同,但是这里提出的问题是不同的问题。(顺便说一句,您可以使用托管代码中的 COM 包装器来调用 UIAutomation dll 的正确版本,这将解决诸如“inspect.exe 找到它但我的托管代码不能”之类的问题)。

我也遇到了这里提出的问题(我的问题是: FindAll(TreeScope.Children, TrueCondition) 没有返回任何东西,尽管 FindFirst() 成功地返回了同一控件上的子项)。

我尝试了 mike-z 的方法,使用 RawViewWalker 来寻找孩子,它在这种情况下效果很好。我正在写这个单独的答案,说问题不是 Find* 方法,而是导致 August 问题的 FindAll 和 FindFirst 方法之间的差异。

更新

对于 MS 工具,不一致的行为似乎是常态。进行此更新的原因是,我在使用 C# 的 tlbimp.exe'd RCW for uia 遇到了类似的问题,这次我编写了一个直接等效的 C 代码,令我惊讶的是它在 C# 代码中运行良好在试图找到一个简单的 OpenFileDialog 控件时拒绝以任何方式工作,然后在主窗体上找到另一个控件。两个世界的唯一区别是神秘的 MS RCW 魔法。我不确定这是否是使用自动创建的 COM 包装器(通过 tlbimp)或其他方式处理封送处理的方式。并且为创建的界面显示的 [ComConversionLoss] 属性对我来说听起来不正确。反正我

于 2015-10-09T03:47:53.520 回答
1

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

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

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

于 2015-02-01T16:49:21.750 回答
1

托管和非托管 UI 自动化之间的区别在于托管使用旧实现,但 Inspect 直接使用 COM,这是较新的 3.0 版

于 2015-03-31T13:24:17.200 回答
1

我原来的例子是简化的。我尝试使用 3 种技术访问儿童:

  1. .Net 托管代码中的 RawViewWalker。
  2. COM 中的等效 walker,即 .Net 托管代码中可用的 COM 包装器。
  3. 我编写的一个完全独立的 VB6 应用程序中的非 .Net 代码(即非托管代码)。

只有 VB6(非托管)代码给出了与 Microsoft 的 Inspect 工具相同的结果。我相信这证实了上面其他人所说的:Microsoft 在 .Net 中的 UI 自动化实现存在严重问题。可能唯一的解决方案是在 .Net 中编写自定义 UI 自动化客户端,但这假设目标应用程序中的 UI 自动化服务器行为正确。这些超出了我的控制范围,因为目标应用程序是由其他公司编写的,而不是我的。

于 2017-09-27T16:03:07.723 回答
0

为了让 FindFirst 找到后代,目标元素必须设置 IsControlElement。

在原始海报的屏幕截图中,IsControlElement 被报告为[Not supported].

换句话说,FindFirst 搜索控制树,而不是原始树。

于 2021-10-22T01:29:57.870 回答