我有一个.NET 2.0 WebBrowser控件,用于导航一些没有用户交互的页面(不要问......长篇故事)。由于此应用程序的用户性质较少,我已将WebBrowser控件的ScriptErrorsSuppressed属性设置为true,VS 2005状态中包含的文档将“隐藏其源自底层ActiveX控件的所有对话框,不只是脚本错误。“但是MSDN article没有提到这一点。 我已经设法取消NewWindow事件,这会阻止弹出窗口,因此需要处理。
任何人都有使用其中任何一个并成功阻止所有对话框,脚本错误等的经验?
修改
这不是IE的独立实例,而是生活在Windows窗体应用程序上的WebBrowser控件的实例。任何人都有使用此控件或基础控件的经验 AxSHDocVW ?
再次编辑
抱歉,我忘了提到这个......我正试图阻止一个 JavaScript警报(),只需一个OK按钮。也许我可以转换成IHTMLDocument2对象并以这种方式访问脚本,我曾经使用过MSHTML,有人知道吗?
答案 0 :(得分:12)
要想轻松注入javascript的神奇系列,请阅读how to inject javascript into webbrowser control。
或者只使用这个完整的代码:
private void InjectAlertBlocker() {
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
string alertBlocker = "window.alert = function () { }";
scriptEl.SetAttribute("text", alertBlocker);
head.AppendChild(scriptEl);
}
答案 1 :(得分:7)
这绝对是hacky,但是如果你使用WebBrowser控件做任何工作,你会发现自己做了很多hacky东西。
这是我所知道的最简单的方法。你需要注入JavaScript来覆盖警报功能...这就像注入这个JavaScript函数一样:
window.alert = function () { }
有很多方法可以做到这一点,但很有可能。一种可能性是挂钩DWebBrowserEvents2接口的实现。完成此操作后,您可以插入NavigateComplete,DownloadComplete或DocumentComplete(或者,如我们所做的,它的一些变体),然后调用您实现的InjectJavaScript方法,该方法执行窗口覆盖.alert方法
就像我说的那样,hacky,但它有效:)
如果需要,我可以详细介绍。
答案 2 :(得分:6)
您可能需要自定义一些内容,查看IDocHostUIHandler
,然后查看其他一些相关的界面。您可以进行相当多的控制,甚至可以自定义对话框显示/ ui(我无法回想起这个界面)。我很确定你可以做你想做的事,但它确实需要在MSHTML
的内部进行处理,并能够实现各种COM
接口。
其他一些想法: http://msdn.microsoft.com/en-us/library/aa770041.aspx
IHostDialogHelper
IDocHostShowUI
这些可能是您正在实施的内容。
答案 3 :(得分:5)
防弹警报拦截器:
Browser.Navigated +=
new WebBrowserNavigatedEventHandler(
(object sender, WebBrowserNavigatedEventArgs args) => {
Action<HtmlDocument> blockAlerts = (HtmlDocument d) => {
HtmlElement h = d.GetElementsByTagName("head")[0];
HtmlElement s = d.CreateElement("script");
IHTMLScriptElement e = (IHTMLScriptElement)s.DomElement;
e.text = "window.alert=function(){};";
h.AppendChild(s);
};
WebBrowser b = sender as WebBrowser;
blockAlerts(b.Document);
for (int i = 0; i < b.Document.Window.Frames.Count; i++)
try { blockAlerts(b.Document.Window.Frames[i].Document); }
catch (Exception) { };
}
);
此示例假设您添加了 Microsoft.mshtml 引用,“使用mshtml; ”在您的命名空间中,浏览器是您的 WebBrowser 实例。
为什么它是防弹的?首先,它处理框架内的脚本。然后,当文档中存在特殊的“杀手框架”时,不会崩溃。 “杀手框架”是一个在尝试将其用作HtmlWindow对象时引发异常的框架。 Document.Window.Frames上使用的任何“foreach”都会导致异常,因此必须在try / catch块中使用更安全的“for”循环。
也许它不是最易读的代码片段,但它适用于现实生活中,格式错误的页面。
答案 4 :(得分:3)
webBrowser1.ScriptErrorsSuppressed = true;
只需将其添加到您的入门级功能即可。经过大量的研究,当我遇到这种方法,并触摸木材,直到现在它的工作。干杯!!
答案 5 :(得分:3)
window.showModelessDialog和window.showModalDialog可以通过实现INewWindowManager接口来阻止,另外下面的代码显示了如何通过实现IDocHostShowUI来阻止警报对话框
public class MyBrowser : WebBrowser
{
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
public MyBrowser()
{
}
protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
{
var manager = new NewWindowManagerWebBrowserSite(this);
return manager;
}
protected class NewWindowManagerWebBrowserSite : WebBrowserSite, IServiceProvider, IDocHostShowUI
{
private readonly NewWindowManager _manager;
public NewWindowManagerWebBrowserSite(WebBrowser host)
: base(host)
{
_manager = new NewWindowManager();
}
public int ShowMessage(IntPtr hwnd, string lpstrText, string lpstrCaption, int dwType, string lpstrHelpFile, int dwHelpContext, out int lpResult)
{
lpResult = 0;
return Constants.S_OK; // S_OK Host displayed its UI. MSHTML does not display its message box.
}
// Only files of types .chm and .htm are supported as help files.
public int ShowHelp(IntPtr hwnd, string pszHelpFile, uint uCommand, uint dwData, POINT ptMouse, object pDispatchObjectHit)
{
return Constants.S_OK; // S_OK Host displayed its UI. MSHTML does not display its message box.
}
#region Implementation of IServiceProvider
public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
if ((guidService == Constants.IID_INewWindowManager && riid == Constants.IID_INewWindowManager))
{
ppvObject = Marshal.GetComInterfaceForObject(_manager, typeof(INewWindowManager));
if (ppvObject != IntPtr.Zero)
{
return Constants.S_OK;
}
}
ppvObject = IntPtr.Zero;
return Constants.E_NOINTERFACE;
}
#endregion
}
}
[ComVisible(true)]
[Guid("01AFBFE2-CA97-4F72-A0BF-E157038E4118")]
public class NewWindowManager : INewWindowManager
{
public int EvaluateNewWindow(string pszUrl, string pszName,
string pszUrlContext, string pszFeatures, bool fReplace, uint dwFlags, uint dwUserActionTime)
{
// use E_FAIL to be the same as CoInternetSetFeatureEnabled with FEATURE_WEBOC_POPUPMANAGEMENT
//int hr = MyBrowser.Constants.E_FAIL;
int hr = MyBrowser.Constants.S_FALSE; //Block
//int hr = MyBrowser.Constants.S_OK; //Allow all
return hr;
}
}
答案 6 :(得分:2)
我刚刚发表了一篇关于代码项目的文章,可能对您有帮助。
请参阅 - http://www.codeproject.com/KB/shell/WebBrowserControlDialogs.aspx
希望这有帮助。
答案 7 :(得分:2)
InjectAlertBlocker
绝对正确
代码是
private void InjectAlertBlocker() {
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
string alertBlocker = "window.alert = function () { }";
element.text = alertBlocker;
head.AppendChild(scriptEl);
}
需要添加的参考是
添加对MSHTML
的引用,该引用将在COM
引用下被称为“ Microsoft HTML对象库”。
将using mshtml;
添加到您的命名空间。
获取对您的脚本元素IHTMLElement
:
然后您可以使用webbrowser的Navigated
事件:
private void InjectAlertBlocker()
{
HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser1.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
string alertBlocker = "window.alert = function () { }";
element.text = alertBlocker;
head.AppendChild(scriptEl);
}
private void webDest_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
InjectAlertBlocker();
}
答案 8 :(得分:0)
您是否正在尝试实施网络机器人?我没有使用托管IE控件的经验,但我确实完成了一些尝试使用IE控件的Win32项目。禁用弹出窗口应该通过控件的事件处理程序完成,但我发现你还需要更改IE选项中的“禁用脚本调试xxxx”(或者你可以修改代码中的注册表) cjheath已经指出了。但是,我还发现在检查导航URL以查找任何可下载内容时需要执行额外的步骤,以防止这些打开/保存对话框。但我不知道如何处理流文件,因为我不能单独查看网址跳过它们,最后我转向Indy库,省去了处理IE的所有麻烦。最后,我记得微软确实在网上提到IE不能用作OLE控件。根据我自己的经验,每次控件导航到新页面时都会为程序引入内存泄漏!
答案 9 :(得分:0)
我设法通过创建扩展的WebBroswer
类并覆盖OnNavigated
方法来注入上面的代码。
这看起来效果很好:
class WebBrowserEx : WebBrowser
{
public WebBrowserEx ()
{
}
protected override void OnNavigated( WebBrowserNavigatedEventArgs e )
{
HtmlElement he = this.Document.GetElementsByTagName( "head" )[0];
HtmlElement se = this.Document.CreateElement( "script" );
mshtml.IHTMLScriptElement element = (mshtml.IHTMLScriptElement)se.DomElement;
string alertBlocker = "window.alert = function () { }";
element.text = alertBlocker;
he.AppendChild( se );
base.OnNavigated( e );
}
}
答案 10 :(得分:0)
我遇到了更大的问题:加载一个用于打印的网页,它显示恼人的打印对话框。 InjectBlocker是唯一可行的方法,但相当不可靠。在某些条件下(我正在考虑它是因为WebBrowser控件使用IE引擎,这取决于安装的IE版本),仍然会出现打印对话框。这是一个主要问题,解决方案适用于安装了IE9的Win7,但无论如何,带有IE8的WinXP都会显示对话框。
我相信解决方案是在控件呈现页面之前修改源代码并删除print javascript。但是,我尝试使用:webbrowser控件的DocumentText属性,它无法正常工作。该属性不是只读的,但在修改源代码时无效。
我为我的问题找到的解决方案是Exec脚本:
string alertBlocker = "window.print = function emptyMethod() { }; window.alert = function emptyMethod() { }; window.open = function emptyMethod() { };";
this.Document.InvokeScript("execScript", new Object[] { alertBlocker, "JavaScript" });
答案 11 :(得分:0)
只需从浏览器控件属性:scriptErrorSupressed = true
答案 12 :(得分:0)
最简单的方法是:
在:Webbrowser Control中,您有程序(标准)BeforeScriptExecute
(BeforeScriptExecute
的参数为pdispwindow
)
添加:
pdispwindow.execscript("window.alert = function () { }")
以这种方式,在页面窗口警报上的任何脚本执行将被注入的代码抑制之前。