DWebBrowserEvents2 event OnQuit fired multiple times

674 Views Asked by At

We are using an Internet Explorer object (Interop.SHDocVw, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null) to open a explorer outside a WPF application.

We need to know when the explorer closes so we handle the OnQuit event but we are receiving the event multiple times due to unknown reasons depending on the URL.

The following POC demonstrates the issue:

using System;

namespace InternetExplorerQuitPOC
{
    class Program
    {
        static void Main(string[] args)
        {
            do
            {
                SHDocVw.InternetExplorer internetExplorer;

                internetExplorer = new SHDocVw.InternetExplorer();
                internetExplorer.OnQuit += OnInternetExplorerOnOnQuit;

                internetExplorer.ToolBar = 1;
                internetExplorer.StatusBar = true;
                internetExplorer.MenuBar = true;
                internetExplorer.Visible = true;

                object url = "https://www.notariado.org";

                internetExplorer.Navigate2(ref url);
            } while (Console.ReadKey() != null);
        }

        private static void OnInternetExplorerOnOnQuit()
        {
            Console.Out.WriteLine("Quit fired");
        }
    }
}
2

There are 2 best solutions below

1
Ignacio Soler Garcia On BEST ANSWER

It turns out that the OnQuit event is raised in more situations than just closing the browser, for example, if the page has an inside IE will raise the OnQuit as well so the OnQuit event is not reliable to know when IE has been closed so I've found a way to know it in a reliable way:

        uint processId;
        this.internetExplorer = new InternetExplorer();

        NativeMethods.GetWindowThreadProcessId(new IntPtr(this.internetExplorer.HWND), out processId);
        this.internetExplorerProcess = Process.GetProcessById(Convert.ToInt32(processId));
        this.internetExplorerProcess.EnableRaisingEvents = true;
        this.internetExplorerProcess.Exited += this.OnQuit;

This code will call the OnQuit only when the process is finished as it should do the InternetExplorer object (sigh).

0
Javi Quirós On

For Ignacio.

Your solution is not 100% valid, internet explorer reuses the same processes when opening different browsers, which causes the Exited event to only run on the Close of the last browser that shares the process, this may be a browser that does not interest us.

The steps I have followed to implement a valid solution are:

  1. Create a Process.Start("iexplorer", "- noframemerging") -noframemerging: Internet Explorer 8 and later versions. Prevents Internet Explorer from opportunistically merging new frame processes into existing frame processes. This has the effect of preventing session merging as well, because session merging can only happen with a merged frame process.

    This guarantees that our navigation is not merged with other Internet Explorer processes.

  2. Associate that process with SHDocVw.InternetExplorer object.

  3. Configure SHDocVw.InternetExplorer object, window size, visibility of the toolbar ...

  4. Subscribe to Process Exited.

  5. SHDocVw.InternetExplorer.Navigate2 ("url")

  6. Close the new Internet Explorer process.

  7. We will now receive the Exited event of the desired process.

Point 1 is the key to solving the problem. Sorry for my level of English. (I will post an example code)

Ignacio, we miss you :P