C# .NET WebBrowser 控件中的阻止对话框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/77659/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:15:45  来源:igfitidea点击:

Blocking dialogs in .NET WebBrowser control

提问by Adam Neal

I have a .NET 2.0WebBrowser control used to navigate some pages with no user interaction (don't ask...long story). Because of the user-less nature of this application, I have set the WebBrowser control's ScriptErrorsSuppressed property to true, which the documentation included with VS 2005 states will [...]"hide all its dialog boxes that originate from the underlying ActiveX control, not just script errors." The MSDN articledoesn't mention this, however. I have managed to cancel the NewWindow event, which prevents popups, so that's taken care of.

我有一个 .NET 2.0WebBrowser 控件,用于在没有用户交互的情况下导航某些页面(不要问......长篇大论)。由于此应用程序的无用户特性,我已将 WebBrowser 控件的 ScriptErrorsSuppressed 属性设置为 true,VS 2005 中包含的文档说明将 [...]“隐藏其源自底层 ActiveX 控件的所有对话框,不仅仅是脚本错误。” 然而,MSDN 文章没有提到这一点。我设法取消了防止弹出窗口的 NewWindow 事件,所以这已经解决了。

Anyone have any experience using one of these and successfully blocking alldialogs, script errors, etc?

任何人都有使用其中之一并成功阻止所有对话框、脚本错误等的经验?

EDIT

编辑

This isn't a standalone instance of IE, but an instance of a WebBrowser control living on a Windows Form application. Anyone have any experience with this control, or the underlying one, AxSHDocVW?

这不是 IE 的独立实例,而是存在于 Windows 窗体应用程序上的 WebBrowser 控件的实例。任何人都对此控件或底层控件AxSHDocVW有任何经验?

EDIT again

再次编辑

Sorry I forgot to mention this... I'm trying to block a JavaScript alert(), with just an OK button. Maybe I can cast into an IHTMLDocument2 object and access the scripts that way, I've used MSHTML a little bit, anyone know?

抱歉,我忘了提及这一点...我正在尝试使用一个 OK 按钮来阻止JavaScript alert()。也许我可以转换成 IHTMLDocument2 对象并以这种方式访问​​脚本,我已经使用了一点 MSHTML,有人知道吗?

采纳答案by David Mohundro

This is most definitely hacky, but if you do any work with the WebBrowser control, you'll find yourself doing a lot of hacky stuff.

这绝对是hacky,但是如果您使用WebBrowser 控件进行任何工作,您会发现自己做了很多hacky 的事情。

This is the easiest way that I know of to do this. You need to inject JavaScript to override the alert function... something along the lines of injecting this JavaScript function:

这是我所知道的最简单的方法。您需要注入 JavaScript 来覆盖警报功能……类似于注入此 JavaScript 函数的内容:

window.alert = function () { }

There are many ways to do this, but it is very possible to do. One possibility is to hook an implementation of the DWebBrowserEvents2interface. Once this is done, you can then plug into the NavigateComplete, the DownloadComplete, or the DocumentComplete (or, as we do, some variation thereof) and then call an InjectJavaScript method that you've implemented that performs this overriding of the window.alert method.

很多方法可以做到这一点,但很有可能做到。一种可能性是挂钩DWebBrowserEvents2接口的实现。完成此操作后,您可以插入 NavigateComplete、DownloadComplete 或 DocumentComplete(或者,正如我们所做的,它们的一些变体),然后调用您已实现的 InjectJavaScript 方法,该方法执行此覆盖 window.alert方法。

Like I said, hacky, but it works :)

就像我说的,hacky,但它有效:)

I can go into more details if I need to.

如果需要,我可以详细介绍。

回答by William

Are you trying to implement a web robot? I have little experience in using the hosted IE control but I did completed a few Win32 projects tried to use the IE control. Disabling the popups should be done via the event handlers of the control as you already did, but I found that you also need to change the 'Disable script debugging xxxx' in the IE options (or you could modify the registry in your codes) as cjheath already pointed out. However I also found that extra steps needed to be done on checking the navigating url for any downloadable contents to prevent those open/save dialogs. But I do not know how to deal with streaming files since I cannot skip them by looking at the urls alone and in the end I turned to the Indy library saving me all the troubles in dealing with IE. Finally, I remember Microsoft did mention something online that IE is not designed to be used as an OLE control. According to my own experience, every time the control navigates to a new page did introduce memory leaks for the programs!

你想实现一个网络机器人吗?我几乎没有使用托管 IE 控件的经验,但我确实完成了一些尝试使用 IE 控件的 Win32 项目。禁用弹出窗口应该通过控件的事件处理程序完成,但我发现您还需要更改 IE 选项中的“禁用脚本调试 xxxx”(或者您可以修改代码中的注册表)作为cjheath 已经指出。但是,我还发现需要执行额外的步骤来检查任何可下载内容的导航 url,以防止出现这些打开/保存对话框。但是我不知道如何处理流文件,因为我无法通过单独查看 url 来跳过它们,最后我转向了 Indy 库,为我省去了处理 IE 的所有麻烦。最后,我记得微软确实在网上提到过 IE 不是用来作为 OLE 控件的。根据我自己的经验,每次控件导航到新页面时都会为程序引入内存泄漏!

回答by Jim Crafton

You may have to customize some things, take a look at IDocHostUIHandler, and then check out some of the other related interfaces. You can have a fair amount of control, even to the point of customizing dialog display/ui (I can't recall which interface does this). I'm pretty sure you can do what you want, but it does require mucking around in the internals of MSHTMLand being able to implement the various COMinterfaces.

您可能需要自定义一些内容,查看IDocHostUIHandler,然后查看其他一些相关接口。您可以进行大量控制,甚至可以自定义对话框显示/用户界面(我不记得是哪个界面执行此操作)。我很确定你可以做你想做的事,但它确实需要在内部进行处理MSHTML并能够实现各种COM接口。

Some other ideas: http://msdn.microsoft.com/en-us/library/aa770041.aspx

其他一些想法:http: //msdn.microsoft.com/en-us/library/aa770041.aspx

IHostDialogHelper
IDocHostShowUI

These may be the things you're looking at implementing.

这些可能是您正在考虑实施的事情。

回答by Sire

And for an easy way to inject that magic line of javascript, read how to inject javascript into webbrowser control.

要获得一种简单的方法来注入那条神奇的 javascript 代码,请阅读如何将 javascript 注入 webbrowser 控件

Or just use this complete code:

或者只是使用这个完整的代码:

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);
}

回答by Sire

I just published an article on Code Project that may help you.

我刚刚发表了一篇关于 Code Project 的文章,可能对你有所帮助。

Please see - http://www.codeproject.com/KB/shell/WebBrowserControlDialogs.aspx

请参阅 - http://www.codeproject.com/KB/shell/WebBrowserControlDialogs.aspx

Hope this helps.

希望这可以帮助。

回答by Sire

I managed to inject the code above by creating an extended WebBroswerclass and overriding the OnNavigatedmethod.

This seemed to work quite well:

我设法通过创建一个扩展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 );
  }
}

回答by abobjects.com

The InjectAlertBlockeris absolutely correct code is

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);
}

References needed to be added is

需要添加的引用是

  1. Add a reference to MSHTML, which will probalby be called "Microsoft HTML Object Library" under COMreferences.

  2. Add using mshtml;to your namespaces.

  3. Get a reference to your script element's IHTMLElement:

  1. 添加对 的引用MSHTML,它可能在引用下称为“ Microsoft HTML 对象库COM

  2. 添加using mshtml;到您的命名空间。

  3. 获取对脚本元素的引用IHTMLElement

Then you can use the Navigatedevent of webbrowser as:

然后你可以使用Navigatedwebbrowser的事件作为:

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();
}

回答by Prashant Bassi

webBrowser1.ScriptErrorsSuppressed = true;

Just add that to your entry level function. After alot of research is when I came across this method, and touch wood till now its worked. Cheers!!

只需将其添加到您的入门级功能即可。经过大量研究后,我发现了这种方法,直到现在它才起作用。干杯!!

回答by Legoless

I had bigger problems with this: loading a webpage that is meant for printing and it displays annoying Print dialog. The InjectBlocker was the only way that worked, but fairly unreliable. Under certain conditions (I am considering it's due that WebBrowser control uses IE engine and this depends on installed IE version) the print dialog still appears. This is a major problem, the solution works on Win7 with IE9 installed, but WinXP with IE8 displays the dialog, no matter what.

我在这方面遇到了更大的问题:加载了一个用于打印的网页,它显示了烦人的打印对话框。InjectBlocker 是唯一有效的方法,但相当不可靠。在某些情况下(我认为这是由于 WebBrowser 控件使用 IE 引擎,这取决于安装的 IE 版本)打印对话框仍然出现。这是一个大问题,该解决方案适用于安装了 IE9 的 Win7,但安装了 IE8 的 WinXP 显示对话框,无论如何。

I believe the solution is in modifying source code and removing the print javascript, before control renders the page. However I tried that with: DocumentText property of the webbrowser control and it is not working. The property is not read only, but it has no effect, when I modify the source.

我相信解决方案是在控件呈现页面之前修改源代码并删除打印 javascript。但是我尝试了: webbrowser 控件的 DocumentText 属性,但它不起作用。该属性不是只读的,但是当我修改源时它没有任何影响。

The solution I found for my problem is the Exec script:

我为我的问题找到的解决方案是 Exec 脚本:

string alertBlocker = "window.print = function emptyMethod() { }; window.alert = function emptyMethod() { }; window.open = function emptyMethod() { };";    
this.Document.InvokeScript("execScript", new Object[] { alertBlocker, "JavaScript" });

回答by Harry

Bulletproof alert blocker:

防弹警报拦截器:

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) { };
        }
    );

This sample assumes you have Microsoft.mshtmlreference added, "using mshtml;" in your namespaces and Browseris your WebBrowserinstance.

此示例假定您在命名空间中添加了Microsoft.mshtml引用“ using mshtml;”,并且Browser是您的WebBrowser实例。

Why is it bulletproof? First, it handles scripts inside frames. Then, it doesn't crashwhen a special "killer frame"exists in document. A "killer frame"is a frame which raises an exception on attempt to use it as HtmlWindow object. Any "foreach" used on Document.Window.Frames would cause an exception, so safer "for" loop must be used with try / catch block.

为什么是防弹的?首先,它处理 frame 内的脚本。然后,当文档中存在特殊的“杀手框架”时,它不会崩溃。阿“杀手帧”是这引起了上尝试使用它作为HtmlWindow对象异常的帧。Document.Window.Frames 上使用的任何“foreach”都会导致异常,因此必须将更安全的“for”循环与 try/catch 块一起使用。

Maybe it's not the most readable piece of code, but it works with real life, ill-formed pages.

也许它不是最易读的一段代码,但它适用于现实生活中的格式错误的页面。