26

我们正在开发一个内部使用的 WPF 4.0 应用程序。
在某些客户端上,由于 UI 自动化,我们遇到了巨大的性能问题(这些客户端安装了平板电脑服务笔、触控等软件)。

这是 WPF 4.0 的一个已知问题,例如:


我们已经能够在规格非常有限的机器上重现此问题。在这台机器上打开一个 WPF 窗口需要:

  • 00:00:02 - 未安装任何 UI 自动化触发软件
  • 00:01:41 - 安装了 UI 自动化触发软件(用于此测试的 RoboForm)
  • 00:00:09 - 安装了 UI 自动化触发软件,并应用了修补程序 KB2484841

如您所见,安装修补程序 KB2484841 是一个巨大的改进,但仍然不如没有安装 ui 自动化触发软件的运行速度。
此外,我们对在客户端安装哪些软件没有太多控制权,因此很难为所有客户端推出此修复程序。


因此,是否可以“关闭”整个 WPF 应用程序的 UI 自动化?我知道它可以在每个 UserControl 的基础上完成,但整个应用程序是否可能?

我已经尝试过这篇文章中提供的代码,但没有成功。


谢谢你的时间,
科恩

4

5 回答 5

17

我们遇到了问题中提到的完全相同的问题,即 UI 自动化客户端正在影响我们WPF应用程序的性能。

在尝试了所有的热修复和变通方法后,我们终于找到了解决方案。每个 UI 控件都有一个AutomationPeer对象,该对象公开当前控件及其子控件的属性。UI 自动化客户端使用这些AutomationPeer对象来获取有关 UI 控件的信息。大多数 UI 控件都有内置的自动化对等类,WPF我们还可以创建自定义对等类。

以下是自定义自动化对等类。请注意,在该GetChildrenCore方法中,它返回的是一个空列表,而不是实际子控件的列表。

public class CustomWindowAutomationPeer : FrameworkElementAutomationPeer
{
    public CustomWindowAutomationPeer(FrameworkElement owner) : base(owner) { }

    protected override string GetNameCore()
    {
        return "CustomWindowAutomationPeer";
    }

    protected override AutomationControlType GetAutomationControlTypeCore()
    {
        return AutomationControlType.Window;
    }

    protected override List<AutomationPeer> GetChildrenCore()
    {
        return new List<AutomationPeer>();
    }
}

然后在您的主窗口中,覆盖该OnCreateAutomationPeer方法:

protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
{
    return new CustomWindowAutomationPeer(this);
}

现在,当 UI 自动化客户端尝试获取主窗口的子控件时,它会返回一个空列表,因此它无法遍历其余控件。

有关详细信息,请参阅此MSDN 文章

于 2014-10-17T21:36:24.250 回答
3

DevExpress控件也有同样的问题。两种解决方法代码都对我们没有帮助。而且我认为没有任何“开关”可以禁用 UI 自动化。但是自从上一个版本以来,DevExpress 有了神奇的 ClearAutomationEventsHelper类来做一些技巧。据我了解,这个想法是清除导致问题的控件的 AutomationEvents.Count 属性(通过反射)。例如,他们在其基本控件(来自 MeasureOverride)中或每次创建自动化对等时调用此方法。

如果你使用 DevExpress,这个类可以成为你项目的灵丹妙药。我们能够在 WPF 4.0 项目中完全避免 UI 自动化问题的副作用,客户非常高兴。

于 2013-11-06T19:01:49.543 回答
1

尝试一些货物狂热的编程:

WindowInteropHelper helper = new WindowInteropHelper(mainWindow);
        AutomationElement mainWindowAutomationElement = AutomationElement.FromHandle(helper.Handle);
        Automation.Automation.AddStructureChangedEventHandler(mainWindowAutomationElement, TreeScope.Descendants, AutomationFix);

      void AutomationFix(object sender, StructureChangedEventArgs e)
  {
            AutomationElement element = sender as AutomationElement;
    Automation.Condition condition = new PropertyCondition(AutomationElement.NameProperty, "!!");
    AutomationElement automationElement = element.FindFirst(TreeScope.Children, condition);
  }
于 2013-07-25T00:35:59.230 回答
0

看看这篇文章:

阻止 UI 自动化访问应用程序

据说UIAccess flag可以解决你的问题!

还可以查看这篇文章以创建受信任的证书:

清单和 uiAccess 设置为 true 的问题...

于 2013-06-30T15:00:09.150 回答
-1

您是否尝试过以下操作:

  1. 仅当机器中运行任何自动化客户端(如屏幕阅读器、平板电脑中的 tabtip 等)时,才会触发自动化代码。因此,摆脱这种情况的一种方法是关闭任何这些自动化客户端应用程序。

  2. 如果一个不可行,那么另一种选择是 UIElementHelper.InvalidateAutomationAncestors 仅当应用程序的自动化树稀疏(如果使用自定义窗口自动化对等禁用了建筑自动化树时发生)并且可视化树密集时才会花费更长的时间。所以另一个解决方案是禁用任何自定义自动化代码并允许 WPF 构建完整的自动化树。这也应该加快 UIElementHelper.InvalidateAutomationAncestors 的速度。

这是我发现的关于您的问题的内容,他们也说他们知道这个问题并将尝试解决它。

于 2013-07-05T09:03:21.430 回答