C# 如何(正确地)缓存AutomationElements以备将来使用?

C# 如何(正确地)缓存AutomationElements以备将来使用?,c#,.net,performance,automation,microsoft-ui-automation,C#,.net,Performance,Automation,Microsoft Ui Automation,在我的测试应用程序中,我不断地打开和重新打开一个表单。每次打开表单时,我都必须将表单上的所有元素放入一个AutomationElementCollection,以便对这些元素进行操作。但是,重复获取这些元素似乎代价高昂(由于树导航/上下文切换等原因) 我试图在获取元素的方法周围设置一个布尔值。如果第一次调用该方法,它将正常运行,并将布尔值设置为true。如果第二次调用该方法,它将不会执行任何操作,因为数组已经填充 但是,当我尝试对数组中的任何AutomationElement执行操作时(第二次)

在我的测试应用程序中,我不断地打开和重新打开一个表单。每次打开表单时,我都必须将表单上的所有元素放入一个
AutomationElementCollection
,以便对这些元素进行操作。但是,重复获取这些元素似乎代价高昂(由于树导航/上下文切换等原因)

我试图在获取元素的方法周围设置一个布尔值。如果第一次调用该方法,它将正常运行,并将布尔值设置为true。如果第二次调用该方法,它将不会执行任何操作,因为数组已经填充

但是,当我尝试对数组中的任何
AutomationElement
执行操作时(第二次),这些元素似乎不可用。关闭表单是否会“禁用”这些元素?是否每次打开表单时都必须找到这些元素,以便它们“新鲜”

我研究了
CacheRequest
方法,但这似乎只适用于访问属性/模式,而不是元素

以下是代码/错误消息:

AutomationElement GAP;
AutomationElementcollection GAP1;
private bool initGAP1 = false;
    public void initGAP()
    {
        if (!initGAP1)
        {
            int refnum = ...;
            int refnum2 = ...;
            AutomationElementCollection temp = MMChildren[refnum].FindAll(TreeScope.Children, findCondition);
            GAP = temp.FindAll(TreeScope.Children, findCondition)[refnum2];
            GAP1 = GAP.FindAll(TreeScope.Children, findCondition); //this contains the elements I want to operate on
            initGAP1 = true;
        }
    }

System.Windows.Automation.ElementNotEnabledException:引发了“System.Windows.Automation.ElementNotEnabledException”类型的异常。

您需要重新获取每个新窗口的自动化元素。据我所知,UI自动化框架为您提供了调查运行windows的方法。它将使用不同的技术收集信息,具体取决于目标应用程序使用的框架类型。在您的情况下,如果创建和销毁windows实例,它们将被视为不同的自动元素,因为它们是不同的窗口(基本上,它们在操作系统中具有不同的窗口句柄)。即使底层控制代码相同,它们对操作系统来说也是不同的实例,因此UI自动化也是如此


如果您在遍历过程中遇到性能问题,那么可能值得考虑改用UI自动化COM API,因为在某些操作中,UI自动化COM API的速度要快得多

是的,这是准确的。每次你重新打开那个窗口,那就是一套全新的自动化元件。我支持尝试本机COM API的建议,它通常比托管API性能更好。此外,确保搜索算法尽可能高效(即限制范围,在适当的情况下使用FindFirst而不是FindAll,在可能的情况下使用缓存等)。