19

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

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

编辑

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

再次编辑

对不起,我忘了提这个...我试图阻止JavaScript alert(),只有一个 OK 按钮。也许我可以转换为 IHTMLDocument2 对象并以这种方式访问​​脚本,我已经使用了一点 MSHTML,有人知道吗?

4

12 回答 12

13

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

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

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);
}
于 2008-10-30T19:53:46.730 回答
7

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

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

window.alert = function () { }

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

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

如果需要,我可以详细说明。

于 2008-09-19T12:58:18.073 回答
6

您可能需要自定义一些东西,看看IDocHostUIHandler,然后查看一些其他相关的接口。您可以拥有相当多的控制权,甚至可以自定义对话框显示/用户界面(我不记得哪个界面可以做到这一点)。我很确定你可以做你想做的事,但它确实需要在内部进行处理MSHTML并能够实现各种COM接口。

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

IHostDialogHelper
IDocHostShowUI

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

于 2008-09-21T02:25:53.770 回答
6

防弹警报拦截器:

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引用“ using mshtml; ”,并且Browser是您的WebBrowser实例。

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

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

于 2012-03-21T20:07:58.463 回答
3
webBrowser1.ScriptErrorsSuppressed = true;

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

于 2011-10-26T13:10:59.853 回答
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;
    }
}
于 2013-02-03T06:00:14.027 回答
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);
}

需要添加的参考是

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

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

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

然后您可以将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();
}
于 2011-04-25T16:23:05.630 回答
0

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

于 2008-09-19T01:08:10.817 回答
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 );
  }
}
于 2008-12-01T10:46:14.587 回答
0

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

我相信解决方案是在控件呈现页面之前修改源代码并删除打印 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" });
于 2012-02-23T11:20:35.140 回答
0

只需从浏览器控件属性:scriptErrorSupressed=true

于 2016-01-27T17:29:26.850 回答
0

最简单的方法是: 在:Webbrowser Control 你有程序(标准)BeforeScriptExecute

(参数BeforeScriptExecutepdispwindow

添加这个:

pdispwindow.execscript("window.alert = function () { }")

这样,在页面窗口上的任何脚本执行之前,警报都会被注入的代码抑制。

于 2016-03-28T08:09:29.333 回答