DWebBrowserEvents2 事件 OnQuit 多次触发
DWebBrowserEvents2 event OnQuit fired multiple times
我们正在使用 Internet Explorer 对象 (Interop.SHDocVw, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null
) 在 WPF 应用程序外部打开资源管理器。
我们需要知道资源管理器何时关闭,因此我们处理了 OnQuit 事件,但由于未知原因,我们多次收到该事件,具体取决于 URL。
以下 POC 演示了该问题:
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");
}
}
}
事实证明,除了关闭浏览器之外,在更多情况下会引发 OnQuit 事件,例如,如果页面有内部 IE 也会引发 OnQuit,因此 OnQuit 事件无法可靠地知道何时 IE已经关闭,所以我找到了一种可靠的方式来了解它:
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;
此代码将仅在进程完成时调用 OnQuit,因为它应该调用 InternetExplorer 对象(叹息)。
为伊格纳西奥
您的解决方案不是 100% 有效,Internet Explorer 在打开不同的浏览器时重复使用相同的进程,这导致 Exited 事件仅在最后一个共享进程的浏览器关闭时 运行,这可能成为我们不感兴趣的浏览器。
我为实施有效解决方案所遵循的步骤是:
创建一个Process.Start("iexplorer", "- noframemerging")
-noframemerging:Internet Explorer 8 及更高版本。防止 Internet Explorer 机会性地将新框架进程合并到现有框架进程中。这也具有防止会话合并的效果,因为会话合并只能在合并的帧进程中发生。
这保证我们的导航不会与其他 Internet Explorer 进程合并。
将该进程与 SHDocVw.InternetExplorer 对象相关联。
配置SHDocVw.InternetExplorer对象,window大小,工具栏可见性...
订阅流程已退出。
SHDocVw.InternetExplorer.Navigate2 ("url")
关闭新的 Internet Explorer 进程。
我们现在将收到所需进程的 Exited 事件。
第1点是解决问题的关键。对不起我的英语水平。
(我将 post 一个示例代码)
伊格纳西奥,我们想念你:P
我们正在使用 Internet Explorer 对象 (Interop.SHDocVw, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null
) 在 WPF 应用程序外部打开资源管理器。
我们需要知道资源管理器何时关闭,因此我们处理了 OnQuit 事件,但由于未知原因,我们多次收到该事件,具体取决于 URL。
以下 POC 演示了该问题:
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");
}
}
}
事实证明,除了关闭浏览器之外,在更多情况下会引发 OnQuit 事件,例如,如果页面有内部 IE 也会引发 OnQuit,因此 OnQuit 事件无法可靠地知道何时 IE已经关闭,所以我找到了一种可靠的方式来了解它:
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;
此代码将仅在进程完成时调用 OnQuit,因为它应该调用 InternetExplorer 对象(叹息)。
为伊格纳西奥
您的解决方案不是 100% 有效,Internet Explorer 在打开不同的浏览器时重复使用相同的进程,这导致 Exited 事件仅在最后一个共享进程的浏览器关闭时 运行,这可能成为我们不感兴趣的浏览器。
我为实施有效解决方案所遵循的步骤是:
创建一个Process.Start("iexplorer", "- noframemerging") -noframemerging:Internet Explorer 8 及更高版本。防止 Internet Explorer 机会性地将新框架进程合并到现有框架进程中。这也具有防止会话合并的效果,因为会话合并只能在合并的帧进程中发生。
这保证我们的导航不会与其他 Internet Explorer 进程合并。
将该进程与 SHDocVw.InternetExplorer 对象相关联。
配置SHDocVw.InternetExplorer对象,window大小,工具栏可见性...
订阅流程已退出。
SHDocVw.InternetExplorer.Navigate2 ("url")
关闭新的 Internet Explorer 进程。
我们现在将收到所需进程的 Exited 事件。
第1点是解决问题的关键。对不起我的英语水平。 (我将 post 一个示例代码)
伊格纳西奥,我们想念你:P