C# 注册UIAutomation结构更改事件
我正在开发一个应用程序,该应用程序监视给定应用程序的自动化事件。目前,我正在开发一个WPF应用程序,专门处理结构更改事件C# 注册UIAutomation结构更改事件,c#,wpf,events,C#,Wpf,Events,我正在开发一个应用程序,该应用程序监视给定应用程序的自动化事件。目前,我正在开发一个WPF应用程序,专门处理结构更改事件 public void MonitorStructureChangedEvents(AutomationElement element) { Automation.AddStructureChangedEventHandler(element, TreeScope.Subtree, OnStructureChanged); } 在这种情况下,元素是应用程序(其主窗口
public void MonitorStructureChangedEvents(AutomationElement element)
{
Automation.AddStructureChangedEventHandler(element, TreeScope.Subtree, OnStructureChanged);
}
在这种情况下,元素
是应用程序(其主窗口)的根自动元素
。所讨论的WPF应用程序只是一个带有网格视图和各种控件(文本框、复选框、按钮等)的窗口。这是我专门为测试UIAutomation事件而开发的测试应用程序
我使用一个单元测试项目来测试这些事件,并使用ClassInitialize
方法启动应用程序。我不会注册StructureChanged
事件,直到应用程序启动并且我通过WMI在我的TestMethod
中找到它。应用程序作为新进程生成
但是,在注册structure changed events时,我会收到应用程序主窗口中所有元素的structure changed events,即使WPF应用程序实际上处于空闲状态。我在主窗口中有一些按钮,用于添加和删除控件以测试StructureChanged
事件,它确实有效,但是我不确定为什么在最初注册时,所有元素都会触发一个StructureChanged事件
编辑:在进一步测试之后,我注意到,只要我单击应用程序窗口或将鼠标悬停在按钮上,就会触发这些事件。然后,它为应用程序中的每个元素触发一次结构更改事件。完成后,如果我将鼠标悬停在按钮上或单击应用程序(即使在单击另一个应用程序或桌面后),它也不再触发结构更改事件
Edit2:经过进一步测试,我相信我找到了问题的原因,但还没有解决方案。当我尝试TreeWalker.RawViewWalker.GetFirstChild(rootApplicationElement)
时,我收到一个空值。我正在获取的AutomationElement
似乎没有缓存子项。一旦我在元素上添加了StructureChanged
事件处理程序,TreeWalker
方法就工作了,我得到了一个有效的元素。当我在这之后激活窗口时,它就会意识到它现在有了所有这些新的子元素。是否有一种方法可以缓存rootApplicationElement
的所有后代,以便在添加事件处理程序之前,我可以遍历整个子树?我可以使用以下方法解决此问题
CacheRequest request = new CacheRequest();
request.TreeScope = TreeScope.Element | TreeScope.Descendants;
using (request.Activate())
{
rootApplicationElement = AutomationElement.RootElement.FindAll(TreeScope.Children,
new PropertyCondition(AutomationElementIdentifiers.ProcessIdProperty, ApplicationInstance.ProcessId))[0];
}
我不建议人们以这种方式获取根元素,因为如果一个应用程序有多个窗口,您将获得多个结果,但这是根据特定的测试需要定制的