如何解决UI 自动化 - 模态对话框可防止自动化
我正在自动化一个应用程序,当自动化使用 Select 时,会打开一个模式对话框,阻止自动化继续。我已经看到这个问题在几个地方讨论过,并提出了一些建议。我已经尝试了所有的建议,但都没有成功。为了发布这个问题,我整理了一个展示相同问题的小应用程序。该应用程序包含一个列表框和一个按钮。当列表框项目选择更改时,它会打开一个消息框。该按钮启动一个自动化序列运行,它选择第一个项目,然后尝试通过按 OK 按钮关闭对话框。
自动化序列在非 UI MTA 线程(任务)中运行。因为 Select 块,它是从另一个非 UI MTA 线程(任务)调用的。当主自动化序列在启动 Select 任务后继续运行时,它会在尝试查找弹出的对话框时挂起。
我看到了添加 WindowOpenedEvent 处理程序并从那里按下 OK 按钮的建议。我已将其包含在此应用程序中,但从未调用处理程序。在我的实际应用程序中,所有其他对话框都会调用处理程序,直到从 Select 调用中打开一个。
关于如何从自动化序列中消除此对话框,还有其他想法吗?
C# .Net 框架 4.8
MainWindow.xaml.cs:
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Interop;
namespace AutomationSelectTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Task _task;
public MainWindow()
{
InitializeComponent();
}
private void ListBox_SelectionChanged(object sender,SelectionChangedEventArgs e)
{
MessageBox.Show("Selection changed");
}
private void Button_Click(object sender,RoutedEventArgs e)
{
var windowHandle = new WindowInteropHelper(this).Handle;
_task = Task.Factory.StartNew(() => AutomationSequence(windowHandle));
}
private static readonly System.Windows.Automation.Condition ButtonOkCondition = new AndCondition(
new PropertyCondition(AutomationElement.ClassNameProperty,"Button"),new PropertyCondition(AutomationElement.NameProperty,"OK"));
private static void AutomationSequence(IntPtr windowHandle)
{
var application = AutomationElement.FromHandle(windowHandle);
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,application,TreeScope.Subtree,Window_Opened);
var listBoxItem = application.FindFirst(TreeScope.Descendants,new PropertyCondition(AutomationElement.ClassNameProperty,"ListBoxItem"));
var listBoxSelectionItemPattern = listBoxItem.GetCurrentPattern(SelectionItemPattern.Pattern) as SelectionItemPattern ?? throw new InvalidOperationException();
// Because the call to Select will block,run it as a separate task
var selectionTask = Task.Factory.StartNew(() => listBoxSelectionItemPattern.Select());
var dialog = application.FindFirst(TreeScope.Children,new PropertyCondition(AutomationElement.LocalizedControlTypeProperty,"Dialog"));
var buttonOk = dialog.FindFirst(TreeScope.Subtree,ButtonOkCondition);
var buttonOkInvokePattern = buttonOk.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern ?? throw new InvalidOperationException();
buttonOkInvokePattern.Invoke();
// Now wait for the Select to return
selectionTask.Wait();
Automation.RemoveAutomationEventHandler(WindowPattern.WindowOpenedEvent,Window_Opened);
}
private static void Window_Opened(object sender,AutomationEventArgs e)
{
// Never gets here
Debugger.Break();
}
}
}
MainWindow.xaml:
<Window x:Class="AutomationSelectTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AutomationSelectTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ListBox HorizontalAlignment="Left" Height="144" Margin="10,10,0" VerticalAlignment="Top" Width="151" SelectionChanged="ListBox_SelectionChanged">
<ListBoxItem Content="ListBoxItem1"/>
<ListBoxItem Content="ListBoxItem2"/>
<ListBoxItem Content="ListBoxItem3"/>
</ListBox>
<Button Content="Run Automation" HorizontalAlignment="Left" Height="39" Margin="10,159,0" VerticalAlignment="Top" Width="151" Click="Button_Click"/>
</Grid>
</Window>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。