【问题标题】:System.Windows.Automation is extremely slowSystem.Windows.Automation 非常慢
【发布时间】:2017-06-05 16:50:42
【问题描述】:

System.Windows.Automation 非常慢。

我执行:

element.FindAll(TreeScope.Children, Condition.TrueCondition);

在速度非常快的计算机上,仅获取 30 个子元素可能需要 1000 毫秒。

我什至看到它在 QT 应用程序中获取 Tree 的子元素时永远挂起。

这是一个已知问题吗? 谷歌搜索了很多后,我找不到任何有用的答案。

【问题讨论】:

    标签: c# com ui-automation


    【解决方案1】:

    System.Windows.Automation 非常

    System.Windows.Automation 充满了错误。它可能不会返回 AutomationElement 的所有子项,这是一个非常严重的错误。

    除此之外,实现是不是线程安全的

    System.Windows.Automation 已弃用。不要使用它!

    MSDN 中,您可以找到以下注释:

    UI 自动化最初是在 Windows XP 中作为 微软 .NET 框架。虽然非托管 C++ API 也是 当时发布,客户端功能的用处有限 因为互操作性问题。对于 Windows 7,API 在组件对象模型 (COM) 中重写。 虽然在早期版本中引入的库函数 UI 自动化仍然记录在案,它们不应该用于新的 应用程序。

    性能下降的解决方案是使用新的 IUIAutomationElement COM 接口,而不是旧的 System.Windows.Automation C# 接口。之后代码将运行闪电般的速度

    除此之外,新界面还提供了更多模式,Microsoft 正在不断对其进行扩展。在 Windows 10 SDK(UIAutomationClient.h 和 UIAutomationCore.h)中添加了一些在 .NET 自动化框架中不可用的模式和属性。

    以下模式在 UIAutomation 的 COM 版本中可用,而 System.Windows.Automation 中不存在:

    • IUIAutomationLegacyIAccessiblePattern
    • IUIAutomationObjectModelPattern
    • IUIAutomationAnnotationPattern
    • IUIAutomationTextPattern2
    • IUIAutomationStylesPattern
    • IUIAutomation 电子表格模式
    • IUIAutomationSpreadsheetItemPattern
    • IUIAutomationTransformPattern2
    • IUIAutomationTextChildPattern
    • IUIAutomationDragPattern
    • IUIAutomationDropTargetPattern
    • IUIAutomationTextEditPattern
    • IUIAutomationCustomNavigationPattern

    另外还添加了以下控件类型:

    • AppBar
    • 语义缩放

    另外还添加了以下元素:

    • IUIAutomationElement2
    • IUIAutomationElement3
    • IUIAutomationElement4

    关于错误:新的 COM UIAutomation 框架设计得非常好,我在框架的客户端上找不到错误,这是一个很大的进步与System.Windows.Automation 相比。但是框架的服务器端 缺少一些功能甚至是错误。在服务器端,每个 GUI 框架都必须实现一个 UIAutomation 提供程序(请参阅MSDN: Interfaces for Providers)。因此,这些问题因您要自动化的应用程序类型而异,因为每个 GUI 框架都有自己的问题:

    原生 Windows GUI 功能缺失:许多控件没有实现它们应该实现的模式。例如,原生工具栏中的 SplitButton 应实现Invoke 模式以单击按钮,并实现ExpandCollapse 模式以打开下拉菜单。但是缺少ExpandCollapse 模式,这使得SplitButtons 难以使用。如果您通过IUIAutomation->ElementFromPoint() 获得一个 Toolbar SplitButton,然后询问它的父级,您将获得一个残缺的元素。而且 Pager 控件根本无法自动化。

    此外,在 WPF 应用程序中,Microsoft 实现的一些控件存在缺陷:例如,如果您有一个 日历 控件,您会在顶部看到两个按钮来切换到下/上个月。如果您在这些按钮上执行Invoke 模式,您将收到UIA_E_NOTSUPPORTED 错误。但这不是框架客户端的错误,因为对于其他按钮,Invoke 模式可以正常工作。这是 WPF 自动化服务器中的一个错误。如果你用 WPF RichTextBox 测试IUIAutomationTextRange,你会发现有几个命令没有实现:Select()ScrollIntoView() 什么都不做。

    对于 .NET Forms 应用程序,Microsoft 没有做出太多努力来支持它们。 .NET 日历 控件根本无法自动化。整个控件甚至不被识别为日历。它具有 ControlType“窗格”,其中没有子元素。这同样适用于 DateTimePicker。而对于像 DataGridPropertyGrid 这样的复杂控件,唯一实现的模式是 LegacyIAccessible,这是一个很差的支持。这些控件应至少实现TableGridScrollItem 模式。

    此外,Internet Explorer 无法自动化,因为可见区域之外的元素由于缺少坐标而无法自动滚动到视图中。 (边界作为空矩形返回)并且ScrollItem 模式没有实现。 (是的,我知道在 Windows 10 中 Internet Explorer 已被 Edge 取代,但 UIAutomation 框架从 Windows 7 开始就存在,并且微软这些年来并没有在 Internet Explorer 中实现有用的自动化支持)

    我什至看到了自动化应用程序的完整崩溃。例如,如果您在某个控件上执行某些自动化命令,Visual Studio 和 TotalCommander 将会崩溃。这里 - 再次 - 错误在于框架的服务器端实现。

    总结:我们有一个很好的框架,但用处有限。开发新 UIAutomation 框架的微软团队做得很好,但微软的其他领域(原生 GUI、WPF、.NET 和 Internet Explorer 团队)不支持这个框架。这是非常可悲的,因为只需要付出很小的努力就可以提供更好的功能。但似乎首先使用 UIAutomation 的用户(残疾人)并不是一个有利可图的市场。

    【讨论】:

    • 我不会将这些问题中的大多数称为错误,而是将它们称为缺乏文档/理解。我应该指出的一件事是,TotalCommander 崩溃不是 UIA 问题。 UIA 毕竟是 UI 客户端应用程序(您的控制器代码)和 UI 服务器(在本例中为 TotalCommander)之间的中介。您应该知道每次使用 UIA 调用时受控制的应用程序会做什么。
    • 我所写的与缺乏理解完全无关。我是 35 年以来的软件开发人员,对 Windows 有非常深入的了解。 UIAutomation 框架有一个服务器端和一个客户端。两者都通过 IPC 进行通信。 TotalCommander 只是一个例子。 Visual Studio 中出现相同的崩溃。两者都使用本机 Windows GUI。在服务器端,有一个严重的错误会导致整个应用程序崩溃。那么为什么你认为这不是一个错误呢?我重新编辑了我的答案以使其更清楚。请再读一遍。
    • 看来你的想法是 TotalCommander 自带了自己的自动化框架。这是错误的。当你自动化一个应用程序时,你与 GUI 框架的自动化提供者进行通信,它是自动化的服务器端。这是定位的错误。如果应用程序在自动化过程中崩溃,则您在 UIA 框架的提供者端(=服务器端)存在严重错误。例如:要获取元素的坐标,请调用 IRawElementProviderFragment->get_BoundingRectangle()。欲了解更多信息,请参阅:msdn.microsoft.com/en-us/library/windows/desktop/…
    • 一个自动化提供程序告诉 UIA 哪个元素对应于一个窗口句柄,它在屏幕上的位置,它的孩子是谁,是否可见等。客户端和服务器双方都运行在 UiAutomationCore.dll 中,您会发现它已加载到两个进程中:自动化进程和自动化进程。对于每个 GUI 框架,都使用了一个单独的自动化提供程序:WPF 具有除 DirectUI 用户界面之外的其他控件,因此每个 GUI 框架的错误都不同。并且 TotalCommander 是使用具有上述错误的本机 Windows GUI 提供程序自动化的。
    • 您写道:“您提到的错误(总指挥官)不是 UIA 的,而是相应调用的提供程序接口实现”。所以你决定提供方不属于 UIA。但这是错误的。提供方也是 UIA 框架的一部分。正如我在更新的答案中所写:UIA 由客户端和服务器(= 提供者)端组成。而我描述的错误是在 UIA 的服务器端。
    猜你喜欢
    • 2015-04-05
    • 2015-05-22
    • 1970-01-01
    • 2017-12-12
    • 2015-06-14
    • 2013-05-14
    • 2021-05-24
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多