user2219063
user2219063

Reputation: 128

Hosting Word in Browser - AutomationElement IsWindowPatternAvailable - how to set it?

We are hosting MS-Word documents in a WebBrowser control in a WPF application.

The WebBrowser control shows the following dialogue during the navigation to a selected MS-Word document:

File Download dialogue

We try to close the dialogue programmatically using AutomationElement. The code works without any problems in a test application. When we adapt the code in our real application (edit the file, show file with mail merge), only the mail merge part is closing the dialogue correctly. In the other case the AutomationElement for the dialogue can not be found.

We have found out that our code is failing when the AutomationElement for the dialogue has IsWindowPatternAvailable = false.

Is there a way to set this property in advance? Or a reason why it is true in one case and false in another?

The test application is a "standard WPF-Application"-project. It only contains the MainWindow.xaml.cs and MainWindow.xaml. Clicking a button sets the Source for the WebBrowser:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Thread thread = new Thread(new ThreadStart(backgroundCheck));
        thread.Start();
        this.TestBrowser.Source = new Uri(@"path-to-document.doc");
        thread.Abort();  
    }

backgroundCheck searches for the specific dialogue and invokes the Open button

    private void backgroundCheck()
    {
        Thread.Sleep(500);
        while (true)
        {

            AutomationElement window = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));

            if (window!= null)
            {
                AutomationElement downloadWindow = window.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));

               if (downloadWindow != null)
                {
                    AutomationElement button = downloadWindow.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "4426"));

                    button.SetFocus();
                     (InvokePattern)button.GetCurrentPattern(InvokePattern.Pattern)).Invoke();
                     return;

                }
            }
        }
    }

Our real application is a bit more complex and uses MVVM, PRISM 5 and WCF. We use WCF to load the Word documents from a server. The files are saved in %temp%.

The two ViewModels (edit document / show merged document, each in a different module) publish an event which the Views subscribe to:

    public class VmExample
    {
        public delegate void BrowserNavigationEventHandler(string pfad);

        public event BrowserNavigationEventHandler browserNavigate;

        private void navigateToDocument()
        {
             browserNavigate("Path-To-Document.doc"); 
        }
    }

    public partial class ViewMerge : UserControl
    {

        private VmExample _vm;

        public ViewMerge()
        {
            InitializeComponent();
            this.DataContextChanged += ViewMerge_DataContextChanged;
        }

        private void ViewMerge_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            this._vm = e.NewValue as VmExample;

            this._vm.browserNavigate += ViewMerge_browserNavigate;
            this.DataContextChanged -= ViewMerge_DataContextChanged;
        }

        private void ViewMerge_browserNavigate(string path)
        {
            Thread threadCheckDownoadWindow = new Thread(backgroundCheck);
            threadCheckDownoadWindow.Start();
            this.wbBrowser.Source = new Uri(path);
            threadCheckDownoadWindow.Abort();
            this._vm.browserNavigate -= ViewMerge_browserNavigate;
        }

    }

We have found the difference in IsWindowPatternAvailable with the help of inspect.exe. When IsWindowPatternAvailable = true the dialogue is a direct child of the Desktop and can be found. When IsWindowPatternAvailable = false we do not see the dialogue in the TreeView of inspect.exe but we can access the properties of the dialogue by clicking on it. In inspect.exe we see the following ancestors:

When we use the code to edit a document in the "merge"-module the dialogue is closed correctly. Both modules reference the same UIAutomation DLLs (UIAutomationClient, UIAutomationProvider).

A similar problem is mentioned here: AutomationElement shows up using Inspect.exe but does show not up ... Using a TreeWalker or searching the complete Subtree of the AutomationElement.RootElement do not work.

Any clues why the IsWindowPatternAvailable behaves that way are welcome. Other suggestions on how to close the File Download dialogue are also welcome.

Upvotes: 2

Views: 317

Answers (1)

user2219063
user2219063

Reputation: 128

Finally found a solution for my problem with the help of this blog using UIAutomationEvents.

    AutomationEventHandler UIAEventHandler = new AutomationEventHandler(OnUIAEvent);

    Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
                    AutomationElement.RootElement,
                    TreeScope.Descendants, UIAEventHandler);
    private static void OnUIAEvent(object src, AutomationEventArgs e)
    {
        AutomationElement element = src as AutomationElement;

        if (element == null)
        {
            return;
        }

        AutomationElement openButton = element.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "4426"));

        if (openButton != null)
        {
            openButton.SetFocus();

            ((InvokePattern)openButton.GetCurrentPattern(InvokePattern.Pattern)).Invoke();
        }
    }

Upvotes: 0

Related Questions