UIAutomation不会检索元素的子元素

时间:2013-01-06 21:44:12

标签: c# windows ui-automation microsoft-ui-automation

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

Inspect screenshot

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

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

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

5 个答案:

答案 0 :(得分:11)

在极少数情况下,我发现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);
       }
    }
}

答案 1 :(得分:2)

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

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

我尝试了使用RawViewWalker查找孩子的mike-z方法,它适用于这种情况。我正在写这个单独的答案,说它不是Find *方法的问题,而是FindAll和amp;之间的区别。导致八月问题的FindFirst方法。

更新

在MS工具方面,不一致的行为似乎是常态。这个更新的原因是,我使用C#对我的tlbimp.exe'd RCW遇到了类似的问题,这次我写了一个直接等效的C代码,令我惊讶的是它在C#代码下工作得很好在尝试查找简单的OpenFileDialog控件时,拒绝以任何方式工作,然后在主窗体上另一个控件。这两个世界的唯一区别是神秘的MS RCW魔法。我不确定是否使用自动创建的COM包装器(通过tlbimp)或其他方式处理编组。并且为创建的界面显示的[ComConversionLoss]属性听起来不对我。无论如何我现在正在考虑手动制作COM接口或将我的整个项目转换为原生环境。

答案 2 :(得分:1)

实际上问题是Inspect.exe是用 unmanaged 代码编写的,而我试图在 managed 代码中获得相同的结果。非托管代码返回的结果与托管版本略有不同(例如,管理代码将返回控件类型document,其中非托管代码将在我的应用程序中返回edit

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

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

我原来的例子很简单。我尝试使用3种技术访问孩子:

  1. .Net托管代码中的RawViewWalker。
  2. COM中的等效walker,即.Net托管代码中提供的COM包装器。
  3. 我编写的完全独立的VB6应用程序中的非.Net代码(即非托管代码)。
  4. 只有VB6(非托管)代码提供与Microsoft的Inspect工具相同的结果。我相信这证实了其他人在上面所说的内容:微软在.Net中实现UI自动化存在严重问题。可能唯一的解决方案是在.Net中编写自定义UI自动化客户端,但这假设目标应用程序中的UI自动化服务器行为正常。这些是我无法控制的,因为目标应用程序是由其他公司编写的,而不是我的。