C# UI自动化-模式对话框阻止自动化

C# UI自动化-模式对话框阻止自动化,c#,wpf,ui-automation,.net-framework-4.8,C#,Wpf,Ui Automation,.net Framework 4.8,我正在自动化一个应用程序,当自动化使用Select时,它会打开一个模式对话框,阻止自动化继续。我看到这个问题在几个地方讨论过,并提出了一些建议。我尝试了所有的建议,但都没有成功。为了发布这个问题,我将一个展示相同问题的小应用程序放在一起。该应用程序包含一个列表框和一个按钮。当列表框项目选择发生更改时,将打开一个消息框。该按钮启动自动序列运行,选择第一个项目,然后按“确定”按钮尝试关闭对话框 自动化序列正在非UI MTA线程任务中运行。由于Select会阻塞,因此会从另一个非UI MTA线程任务调

我正在自动化一个应用程序,当自动化使用Select时,它会打开一个模式对话框,阻止自动化继续。我看到这个问题在几个地方讨论过,并提出了一些建议。我尝试了所有的建议,但都没有成功。为了发布这个问题,我将一个展示相同问题的小应用程序放在一起。该应用程序包含一个列表框和一个按钮。当列表框项目选择发生更改时,将打开一个消息框。该按钮启动自动序列运行,选择第一个项目,然后按“确定”按钮尝试关闭对话框

自动化序列正在非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, application, 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,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,0" VerticalAlignment="Top" Width="151" Click="Button_Click"/>
    
         </Grid>
     </Window>

有人有什么想法吗?当前代码中存在竞争条件,因此必须在StartNew之后引入睡眠,以确保在调用FindFirst之前Select有时间运行。