如何截获WebBrowser控件onbeforeunload事件
展开全部
截获WebBrowser控件onbeforeunload事件:
c# winforms 浏览器web-browser onbeforeunload
我在我所主持的WebBrowser控件内部网页中的WinForms应用程序。 该网页的内容如下:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<title>onbeforeunload test</title>
<meta charset="utf-8">
</head>
<body>
<a href="#" onclick="window.location.reload();">Test</a>
<script type="text/javascript">
window.onbeforeunload = function () {
return 'Are you sure you want to leave this page?';
};
</script>
</body>
</html>
正如你可以看到我已经subscription了onbeforeunload事件,让导航离开此页面前显示确认对话框。这工作得很好,当我点击重新加载页面的锚。在确认对话框显示并可以取消页面的重载。这工作得很好承载控制的WinForms里面。 现在,我有困难的拦截和关闭时的WinForms应用程序(通过点击例如X键)执行此事件。 我能够获取在WinForms应用程序这个函数的内容,但不管是什么我想我是不是能够得到字符串的内容,这个函数返回,使我后来伪造一个MessageBox时试图关闭应用程序:
webBrowser1.Navigated += (sender, e) =>
{
webBrowser1.Document.Window.Load += (s, ee) =>
{
// In order to get the IHTMLWindow2 interface I have referenced
// the Microsoft HTML Object Library (MSHTML) COM control
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
// the bu variable contains the script of the onbeforeunload event
var bu = window.onbeforeunload();
// How to get the string that is returned by this function
// so that I can subscribe to the Close event of the WinForms application
// and show a fake MessageBox with the same text?
};
};
webBrowser1.Navigate(" CodeGo.net
我已经试过了window.execScript方法没有可用的:
// returns null
var script = string.Format("({0})();", bu);
var result = window.execScript(script, "javascript");
我也曾尝试以下 CodeGo.net,但它也返回null:
var result = window.execScript("(function() { return 'foo'; })();", "javascript");
作为最后一招我第三方的JavaScript解析器来,我可以养活这个函数的主体,它会执行它,并返回值,但是这真的是最后的手段。我会很高兴,如果有一个更自然的方式做微软的MSHTML库。更新: 这是现在解决得益于出色的答案@汉斯提供。对于原因,我不能让他在我的测试机(Win7的X64,NET 4.0客户端端配置文件,IE9,EN-US区域设置)解决方案的工作,我总是得到hr = -2147024809后IDispatch.Invoke打电话。所以,我已经修改了IDispatch的P / Invoke签名以下(此签名并不需要引用c:\windows\system32\stdole2.tlb要添加到项目中):
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00020400-0000-0000-C000-000000000046")]
public interface IDispatch
{
[PreserveSig]
int GetTypeInfoCount(out int Count);
[PreserveSig]
int GetTypeInfo(
[MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid,
out ITypeInfo typeInfo
);
[PreserveSig]
int GetIDsOfNames(
ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] rgsNames,
int cNames,
int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId
);
[PreserveSig]
int Invoke(
int dispIdMember,
ref Guid riid,
uint lcid,
ushort wFlags,
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
out object pVarResult,
ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
IntPtr[] pArgErr
);
}
然后我已经subscription了Form的Closing事件,并能够获取由返回onbeforeunload事件提示
protected override void OnFormClosing(FormClosingEventArgs e)
{
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
var args = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
var result = new object();
var except = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
var idisp = window.onbeforeunload as IDispatch;
if (idisp != null)
{
var iid = Guid.Empty;
var lcid = (uint)CultureInfo.CurrentCulture.LCID;
int hr = idisp.Invoke(0, ref iid, lcid, 1, ref args, out result, ref except, null);
if (hr == 0)
{
var msgBox = MessageBox.Show(
this,
(string)result,
"Confirm",
MessageBoxButtons.OKCancel
);
e.Cancel = msgBox == DialogResult.Cancel;
}
}
base.OnFormClosing(e);
}
本文地址 :CodeGo.net/404722/
-------------------------------------------------------------------------------------------------------------------------
1. 本身不显示对话框。返回一个字符串在箱子的主机必须的。由于您的WinForms应用程序是主机它的MessageBox.show()。调用onbeforeunload的是困难的,它是一个IDispatch指针,其(DISPID 0)返回字符串。添加引用c:\windows\system32\stdole2.tlb并粘贴此代码:
using System.Runtime.InteropServices;
...
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
public interface IDispatch {
int dummy1();
int dummy2();
int dummy3();
[PreserveSig]
int Invoke(int dispIdMember, ref Guid riid, int lcid, int dwFlags,
[In, Out] stdole.DISPPARAMS pDispParams,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
[In, Out] stdole.EXCEPINFO pExcepInfo,
[Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
}
你是这样的:
protected override void OnFormClosing(FormClosingEventArgs e) {
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
var args = new stdole.DISPPARAMS();
var result = new object[1];
var except = new stdole.EXCEPINFO();
var idisp = (IDispatch)window.onbeforeunload;
var iid = Guid.Empty;
int hr = idisp.Invoke(0, ref iid, 1033, 1, args, result, except, null);
if (hr == 0) {
if (MessageBox.Show(this, (string)result[0], "Confirm",
MessageBoxButtons.OKCancel) == DialogResult.Cancel) e.Cancel = true;
}
base.OnFormClosing(e);
}
c# winforms 浏览器web-browser onbeforeunload
我在我所主持的WebBrowser控件内部网页中的WinForms应用程序。 该网页的内容如下:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<title>onbeforeunload test</title>
<meta charset="utf-8">
</head>
<body>
<a href="#" onclick="window.location.reload();">Test</a>
<script type="text/javascript">
window.onbeforeunload = function () {
return 'Are you sure you want to leave this page?';
};
</script>
</body>
</html>
正如你可以看到我已经subscription了onbeforeunload事件,让导航离开此页面前显示确认对话框。这工作得很好,当我点击重新加载页面的锚。在确认对话框显示并可以取消页面的重载。这工作得很好承载控制的WinForms里面。 现在,我有困难的拦截和关闭时的WinForms应用程序(通过点击例如X键)执行此事件。 我能够获取在WinForms应用程序这个函数的内容,但不管是什么我想我是不是能够得到字符串的内容,这个函数返回,使我后来伪造一个MessageBox时试图关闭应用程序:
webBrowser1.Navigated += (sender, e) =>
{
webBrowser1.Document.Window.Load += (s, ee) =>
{
// In order to get the IHTMLWindow2 interface I have referenced
// the Microsoft HTML Object Library (MSHTML) COM control
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
// the bu variable contains the script of the onbeforeunload event
var bu = window.onbeforeunload();
// How to get the string that is returned by this function
// so that I can subscribe to the Close event of the WinForms application
// and show a fake MessageBox with the same text?
};
};
webBrowser1.Navigate(" CodeGo.net
我已经试过了window.execScript方法没有可用的:
// returns null
var script = string.Format("({0})();", bu);
var result = window.execScript(script, "javascript");
我也曾尝试以下 CodeGo.net,但它也返回null:
var result = window.execScript("(function() { return 'foo'; })();", "javascript");
作为最后一招我第三方的JavaScript解析器来,我可以养活这个函数的主体,它会执行它,并返回值,但是这真的是最后的手段。我会很高兴,如果有一个更自然的方式做微软的MSHTML库。更新: 这是现在解决得益于出色的答案@汉斯提供。对于原因,我不能让他在我的测试机(Win7的X64,NET 4.0客户端端配置文件,IE9,EN-US区域设置)解决方案的工作,我总是得到hr = -2147024809后IDispatch.Invoke打电话。所以,我已经修改了IDispatch的P / Invoke签名以下(此签名并不需要引用c:\windows\system32\stdole2.tlb要添加到项目中):
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00020400-0000-0000-C000-000000000046")]
public interface IDispatch
{
[PreserveSig]
int GetTypeInfoCount(out int Count);
[PreserveSig]
int GetTypeInfo(
[MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid,
out ITypeInfo typeInfo
);
[PreserveSig]
int GetIDsOfNames(
ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] rgsNames,
int cNames,
int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId
);
[PreserveSig]
int Invoke(
int dispIdMember,
ref Guid riid,
uint lcid,
ushort wFlags,
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
out object pVarResult,
ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
IntPtr[] pArgErr
);
}
然后我已经subscription了Form的Closing事件,并能够获取由返回onbeforeunload事件提示
protected override void OnFormClosing(FormClosingEventArgs e)
{
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
var args = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
var result = new object();
var except = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
var idisp = window.onbeforeunload as IDispatch;
if (idisp != null)
{
var iid = Guid.Empty;
var lcid = (uint)CultureInfo.CurrentCulture.LCID;
int hr = idisp.Invoke(0, ref iid, lcid, 1, ref args, out result, ref except, null);
if (hr == 0)
{
var msgBox = MessageBox.Show(
this,
(string)result,
"Confirm",
MessageBoxButtons.OKCancel
);
e.Cancel = msgBox == DialogResult.Cancel;
}
}
base.OnFormClosing(e);
}
本文地址 :CodeGo.net/404722/
-------------------------------------------------------------------------------------------------------------------------
1. 本身不显示对话框。返回一个字符串在箱子的主机必须的。由于您的WinForms应用程序是主机它的MessageBox.show()。调用onbeforeunload的是困难的,它是一个IDispatch指针,其(DISPID 0)返回字符串。添加引用c:\windows\system32\stdole2.tlb并粘贴此代码:
using System.Runtime.InteropServices;
...
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
public interface IDispatch {
int dummy1();
int dummy2();
int dummy3();
[PreserveSig]
int Invoke(int dispIdMember, ref Guid riid, int lcid, int dwFlags,
[In, Out] stdole.DISPPARAMS pDispParams,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
[In, Out] stdole.EXCEPINFO pExcepInfo,
[Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
}
你是这样的:
protected override void OnFormClosing(FormClosingEventArgs e) {
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
var args = new stdole.DISPPARAMS();
var result = new object[1];
var except = new stdole.EXCEPINFO();
var idisp = (IDispatch)window.onbeforeunload;
var iid = Guid.Empty;
int hr = idisp.Invoke(0, ref iid, 1033, 1, args, result, except, null);
if (hr == 0) {
if (MessageBox.Show(this, (string)result[0], "Confirm",
MessageBoxButtons.OKCancel) == DialogResult.Cancel) e.Cancel = true;
}
base.OnFormClosing(e);
}
2015-04-11 · 知道合伙人数码行家
huanglenzhi
知道合伙人数码行家
向TA提问 私信TA
知道合伙人数码行家
采纳数:117538
获赞数:517195
长期从事计算机组装,维护,网络组建及管理。对计算机硬件、操作系统安装、典型网络设备具有详细认知。
向TA提问 私信TA
关注
展开全部
本身不显示对话框。返回一个字符串在箱子的主机必须的。由于您的WinForms应用程序是主机它的MessageBox.show()。调用onbeforeunload的是困难的,它是一个IDispatch指针,其(DISPID 0)返回字符串。添加引用c:\windows\system32\stdole2.tlb并粘贴此代码:using System.Runtime.InteropServices;
...
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
public interface IDispatch {
int dummy1();
int dummy2();
int dummy3();
[PreserveSig]
int Invoke(int dispIdMember, ref Guid riid, int lcid, int dwFlags,
[In, Out] stdole.DISPPARAMS pDispParams,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
[In, Out] stdole.EXCEPINFO pExcepInfo,
[Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
}
你是这样的: protected override void OnFormClosing(FormClosingEventArgs e) {
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
var args = new stdole.DISPPARAMS();
var result = new object[1];
var except = new stdole.EXCEPINFO();
var idisp = (IDispatch)window.onbeforeunload;
var iid = Guid.Empty;
int hr = idisp.Invoke(0, ref iid, 1033, 1, args, result, except, null);
if (hr == 0) {
if (MessageBox.Show(this, (string)result[0], "Confirm",
MessageBoxButtons.OKCancel) == DialogResult.Cancel) e.Cancel = true;
}
base.OnFormClosing(e);
}
2. 如果你高兴过早执行事件代码(这可以是任何东西)的下列数据串在你的Window.Load;Object[] args = { @"(" + bu + ")();" };
string result = webBrowser1.Document.InvokeScript("eval", args).ToString();
3. 我刚刚处理了一个类似的问题。这是一个迟到的答案,但希望它可以帮助该解决方案基于此MSKB文章。它也适用于情况下,当网页通过处理onbeforeunload事件attachEvent或addEventListener。void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// this code depends on SHDocVw.dll COM interop assembly,
// generate SHDocVw.dll: "tlbimp.exe ieframe.dll",
// and add as a reference to the project
var activeX = this.webBrowser.ActiveXInstance;
object arg1 = Type.Missing;
object arg2 = true;
((SHDocVw.WebBrowser)activeX).ExecWB(SHDocVw.OLECMDID.OLECMDID_ONUNLOAD, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref arg1, ref arg2);
if (!(bool)arg2)
{
e.Cancel = true;
}
}
上面的代码是的WinForms版本WebBrowser控制。对于WPF版本,ActiveXInstance应通过反射首次获得: var activeX = this.WB.GetType().InvokeMember("ActiveXInstance",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, this.WB, new object[] { }) as SHDocVw.WebBrowser;
...
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
public interface IDispatch {
int dummy1();
int dummy2();
int dummy3();
[PreserveSig]
int Invoke(int dispIdMember, ref Guid riid, int lcid, int dwFlags,
[In, Out] stdole.DISPPARAMS pDispParams,
[Out, MarshalAs(UnmanagedType.LPArray)] object[] pVarResult,
[In, Out] stdole.EXCEPINFO pExcepInfo,
[Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] pArgErr);
}
你是这样的: protected override void OnFormClosing(FormClosingEventArgs e) {
var window = (IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
var args = new stdole.DISPPARAMS();
var result = new object[1];
var except = new stdole.EXCEPINFO();
var idisp = (IDispatch)window.onbeforeunload;
var iid = Guid.Empty;
int hr = idisp.Invoke(0, ref iid, 1033, 1, args, result, except, null);
if (hr == 0) {
if (MessageBox.Show(this, (string)result[0], "Confirm",
MessageBoxButtons.OKCancel) == DialogResult.Cancel) e.Cancel = true;
}
base.OnFormClosing(e);
}
2. 如果你高兴过早执行事件代码(这可以是任何东西)的下列数据串在你的Window.Load;Object[] args = { @"(" + bu + ")();" };
string result = webBrowser1.Document.InvokeScript("eval", args).ToString();
3. 我刚刚处理了一个类似的问题。这是一个迟到的答案,但希望它可以帮助该解决方案基于此MSKB文章。它也适用于情况下,当网页通过处理onbeforeunload事件attachEvent或addEventListener。void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// this code depends on SHDocVw.dll COM interop assembly,
// generate SHDocVw.dll: "tlbimp.exe ieframe.dll",
// and add as a reference to the project
var activeX = this.webBrowser.ActiveXInstance;
object arg1 = Type.Missing;
object arg2 = true;
((SHDocVw.WebBrowser)activeX).ExecWB(SHDocVw.OLECMDID.OLECMDID_ONUNLOAD, SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref arg1, ref arg2);
if (!(bool)arg2)
{
e.Cancel = true;
}
}
上面的代码是的WinForms版本WebBrowser控制。对于WPF版本,ActiveXInstance应通过反射首次获得: var activeX = this.WB.GetType().InvokeMember("ActiveXInstance",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, this.WB, new object[] { }) as SHDocVw.WebBrowser;
本回答被提问者和网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询