使用Interop.SHDocVw的IE对象时OnQuit事件多次触发求助
OnQuit Event Triggers for IE Interop Control I’ve run into this exact issue before when working with the SHDocVw.InternetExplorer control in WPF apps. The repeated OnQuit events happen because of how IE’s multi-process model works, combined with the structure of the page you’re navigating to. Let’s break this down and fix it:
Why This Happens
- IE uses a multi-process architecture: when a page loads frames/iframes, popups, or triggers protected mode switches, it spawns child processes. Each of these child processes fires their own
OnQuitevent when they exit, not just the main browser window. - Sites like
https://www.notariado.orgoften load third-party resources or embedded frames, which create those extra child processes. Your event handler picks up every single one of those exits, hence multiple "Quit fired" messages. - On top of that, your POC doesn’t clean up the IE instances or unbind events, which can compound the problem over repeated runs.
Solutions to Fix This
1. Filter Events to Only the Main Window
The InternetExplorer object exposes an HWND property that gives you the main window’s handle. We can track this handle and only respond to OnQuit events that come from the main window, not child processes:
2. Properly Manage COM Object Lifecycle
Always unbind events and release COM objects when they’re no longer needed to avoid memory leaks and stray event triggers.
Here’s the revised POC code implementing these fixes:
using System; using System.Runtime.InteropServices; namespace InternetExplorerQuitPOC { class Program { static void Main(string[] args) { do { SHDocVw.InternetExplorer ieInstance = new SHDocVw.InternetExplorer(); // Capture the main window's handle to filter events later IntPtr mainWindowHandle = new IntPtr(ieInstance.HWND); // Bind the quit event with a reference to the main handle and instance ieInstance.OnQuit += () => HandleIeQuit(mainWindowHandle, ieInstance); // Configure IE window settings ieInstance.ToolBar = 1; ieInstance.StatusBar = true; ieInstance.MenuBar = true; ieInstance.Visible = true; // Navigate to the target URL object targetUrl = "https://www.notariado.org"; ieInstance.Navigate2(ref targetUrl); } while (Console.ReadKey() != null); } private static void HandleIeQuit(IntPtr mainWindowHandle, SHDocVw.InternetExplorer ieInstance) { IntPtr currentWindowHandle = new IntPtr(ieInstance.HWND); // Only react if this is the main window's quit event if (currentWindowHandle == mainWindowHandle) { Console.Out.WriteLine("Main browser window closed!"); // Clean up: unbind event and release the COM object ieInstance.OnQuit -= () => HandleIeQuit(mainWindowHandle, ieInstance); Marshal.ReleaseComObject(ieInstance); } } } }
3. Bonus: Monitor the Main IE Process (More Reliable)
For even better accuracy, you can track the main IE process directly using the Process class. This avoids relying solely on the OnQuit event, which can be noisy:
// After creating the IE instance, grab its process ID System.Diagnostics.Process ieProcess = System.Diagnostics.Process.GetProcessById(ieInstance.ProcessID); // Enable process exit events ieProcess.EnableRaisingEvents = true; ieProcess.Exited += (sender, e) => { Console.Out.WriteLine("Main IE process has exited."); // Clean up here if needed };
This method gives you a definitive signal when the main browser process closes, no matter how many child processes are spawned.
Wrap-Up
The core issue is IE’s multi-process model causing child processes to trigger OnQuit. By filtering events using the main window handle, or monitoring the main process directly, you can reliably detect when the actual browser window closes. Don’t forget to clean up COM objects to prevent memory leaks!
内容的提问来源于stack exchange,提问作者Ignacio Soler Garcia

