可以为整个 WPF 4.0 应用禁用 UI 自动化吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17297539/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 09:04:44  来源:igfitidea点击:

Can UI Automation be disabled for an entire WPF 4.0 app?

.netwpfui-automationmicrosoft-ui-automation

提问by KoenJ

We are developing a WPF 4.0 application for internal use.
On some clients, we are experiencing huge performance issues due to UI automation (these clients have software installed like tablet service pen, touch, ..).

This is a known issue for WPF 4.0, see for instance:

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

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


We've been able to reproduce this issue on a machine with very limited specs. Opening a WPF window on this machine takes:


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

  • 00:00:02 - without any UI automation triggering software installed
  • 00:01:41 - with UI automation triggering software installed (RoboForm for this test)
  • 00:00:09 - with UI automation triggering software installed, and hotfix KB2484841 applied
  • 00:00:02 - 没有安装任何 UI 自动化触发软件
  • 00:01:41 - 安装了 UI 自动化触发软件(此测试的 RoboForm)
  • 00:00:09 - 安装了 UI 自动化触发软件,并应用了修补程序 KB2484841

As you can see, installing hotfix KB2484841 is a huge improvement, but still not as fast as running without ui Automation triggering software installed.
Furthermore, we do not have much control over which software to install at the clients, so it's hard to roll out this fix for all clients.

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



Therefore, is it possible to "turn off" UI Automation for an entire WPF application? I know it can be done on a per-UserControl basis, but is it possible for the app as a whole?

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

I've tried the code provided in thispost, but without success.

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


Thanks for your time,
Koen


谢谢你的时间,
科恩

回答by ImthiyazPH

We hit the exact same issue mentioned in the question, where a UI automation client was impacting the performance of our WPFapplication.

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

After trying all the hot fixes and workarounds, finally we found a solution. Each UI control has an AutomationPeerobject that exposes the properties of the current control and its child controls. The UI automation client uses these AutomationPeerobjects to get the information about the UI controls. There are built-in automation peer class for most of the UI controls in WPFand we can also create a custom peer class.

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

The following is a custom automation peer class. Note that in the GetChildrenCoremethod, it is returning an empty list instead of the list of actual child controls.

以下是自定义自动化对等类。请注意,在该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>();
    }
}

Then in your main window, override the OnCreateAutomationPeermethod:

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

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

Now when the UI automation client tries to get the child controls of the main window, it gets back an empty list and so it cannot iterate through the rest of the controls.

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

Refer this MSDN articlefor more details.

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

回答by Sergei B.

We had the same issue with DevExpresscontrols. Neither workaround code helps to us. And I suppose that there is not any "switch" to disable UI Automation. But since last versions DevExpress have magic ClearAutomationEventsHelperclass that do some tricks. As I understood, the idea is to clear AutomationEvents.Count property (via Reflection) for controls that cause issue. E.g., they call this method in their base controls (from MeasureOverride), or each time automation peer created.

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

If you use DevExpress, this class can be silver bullet for your project. We able totally avoid side effects of UI Automation issues in our WPF 4.0 projects and customers were really happy.

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

回答by Frank R.

Try some cargo-cult programming:

尝试一些货物崇拜编程:

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);
  }

回答by Emmanouil Chountasis

Take a a look at this article :

看看这篇文章:

Preventing UI Automation access to an application

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

It is said that UIAccess flagmay be able to solve your problems!

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

Chack also this article so as to create a Trusted certificate :

Chack 这篇文章,以创建一个受信任的证书:

Problem with manifest and uiAccess set to true...

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

回答by Vlad Vlad

Have you tried the following things:

您是否尝试过以下事情:

  1. Automation code will be triggered only if there are any automation clients ( like screen reader, tabtip in tablet pcs, etc) running in the machine. So one way to get out of this situation is to close any of those automation client apps.

  2. If one is not feasible then an alternative is, UIElementHelper.InvalidateAutomationAncestors will take longer time only if automation tree for the app is sparse ( happens if had disabled building automation tree using custom window automation peer) and visual tree is dense. So another solution is disable any custom automation code and allow WPF to build complete automation tree. This should speed up UIElementHelper.InvalidateAutomationAncestors as well.

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

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

This is what I've found regarding your problem, also they said that they are aware of this issue and will try to fix it.

这是我发现的有关您的问题的信息,他们还表示他们已意识到此问题并将尝试修复它。