使用WPF WebBrowser控件时如何禁止脚本错误?

时间:2009-08-19 07:14:17

标签: wpf browser

我有一个WPF应用程序,它使用WPF WebBrowser控件在平板显示器(如新闻源)上向开发人员显示有趣的网页。

麻烦的是,我偶尔会收到一个HTML脚本错误,弹出一条讨厌的IE错误消息,询问我是否要“停止在此页面上运行脚本”。有没有办法来抑制这个错误检查?

注意:我已经在IE设置中禁用了脚本调试。

9 个答案:

答案 0 :(得分:122)

这是我刚用反射制作的解决方案。解决问题:) 我在Navigated事件中运行它,因为似乎activeX对象在此之前不可用。

它的作用是在底层的activeX对象上设置.Silent属性。这与Windows表单等效的.ScriptErrorsSuppressed属性相同。

 public void HideScriptErrors(WebBrowser wb, bool Hide) {
    FieldInfo fiComWebBrowser = typeof(WebBrowser).GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic);
    if (fiComWebBrowser == null) return;
    object objComWebBrowser = fiComWebBrowser.GetValue(wb);
    if (objComWebBrowser == null) return;
    objComWebBrowser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, null, objComWebBrowser, new object[] { Hide });
 }

可以在.Navigated事件之后随时运行的更好的版本:

public void HideScriptErrors(WebBrowser wb, bool hide) {
    var fiComWebBrowser = typeof(WebBrowser).GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic);
    if (fiComWebBrowser == null) return;
    var objComWebBrowser = fiComWebBrowser.GetValue(wb);
    if (objComWebBrowser == null) {
        wb.Loaded += (o, s) => HideScriptErrors(wb, hide); //In case we are to early
        return;
    }
    objComWebBrowser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, null, objComWebBrowser, new object[] { hide });
}

如果第二个样本出现任何问题,请尝试使用wb.Navigated交换wb.Loaded。

答案 1 :(得分:9)

刚从another question找到,这很优雅,效果很好。

dynamic activeX = this.webBrowser1.GetType().InvokeMember("ActiveXInstance",
                BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
                null, this.webBrowser1, new object[] { });

activeX.Silent = true;

答案 2 :(得分:7)

这里的问题是WPF WebBrowser没有像2.0控件那样实现这个属性。

最好的办法是在WPF应用程序中使用WindowsFormsHost并使用2.0的WebBrowser属性:SuppressScriptErrors。即使这样,您也需要完全信任该应用程序才能执行此操作。

不是人们所说的理想,但它几乎是目前唯一的选择。

答案 3 :(得分:5)

我想将此添加为对@Alkampfer答案的评论,但我没有足够的声誉。这适用于我(Windows 8.1,NET 4.5):

 window.Browser.LoadCompleted.Add(fun _ -> 
    window.Browser.Source <- new System.Uri("javascript:window.onerror=function(msg,url,line){return true;};void(0);"))

此代码示例是用F#编写的,但它的功能非常清楚。

答案 4 :(得分:4)

我还发现了一种有趣的方法来禁用JavaScript错误。但由于使用了优雅的动态类型,您至少需要使用.Net Framework 4.0。

您需要订阅WebBrowser元素的LoadCompleted事件:

<WebBrowser x:Name="Browser" 
            LoadCompleted="Browser_OnLoadCompleted" />

之后你需要编写一个如下所示的事件处理程序:

    void Browser_OnLoadCompleted(object sender, NavigationEventArgs e)
    {
        var browser = sender as WebBrowser;

        if (browser == null || browser.Document == null)
            return;

        dynamic document = browser.Document;

        if (document.readyState != "complete")
            return;

        dynamic script = document.createElement("script");
        script.type = @"text/javascript";
        script.text = @"window.onerror = function(msg,url,line){return true;}";
        document.head.appendChild(script);
    }

答案 5 :(得分:3)

检查以下代码以禁止WPF浏览器控件的脚本错误..

    public MainWindow
    {
    InitializeComponent();
    WebBrowserControlView.Navigate(new Uri("https://www.hotmail.com"));
                        //The below checks for script errors.
    ViewerWebBrowserControlView.Navigated += ViewerWebBrowserControlView_Navigated;
    }

void ViewerWebBrowserControlView_Navigated(object sender, NavigationEventArgs e)
            {
    BrowserHandler.SetSilent(ViewerWebBrowserControlView, true); // make it silent
            }

public static class BrowserHandler
{
    private const string IWebBrowserAppGUID = "0002DF05-0000-0000-C000-000000000046";
    private const string IWebBrowser2GUID = "D30C1661-CDAF-11d0-8A3E-00C04FC9E26E";

    public static void SetSilent(System.Windows.Controls.WebBrowser browser, bool silent)
    {
        if (browser == null)
            MessageBox.Show("No Internet Connection");

        // get an IWebBrowser2 from the document
        IOleServiceProvider sp = browser.Document as IOleServiceProvider;
        if (sp != null)
        {
            Guid IID_IWebBrowserApp = new Guid(IWebBrowserAppGUID);
            Guid IID_IWebBrowser2 = new Guid(IWebBrowser2GUID);

            object webBrowser;
            sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out webBrowser);
            if (webBrowser != null)
            {
                webBrowser.GetType().InvokeMember("Silent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.PutDispProperty, null, webBrowser, new object[] { silent });
            }
        }
    }

}

[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IOleServiceProvider
{
    [PreserveSig]
    int QueryService([In] ref Guid guidService, [In] ref Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);


   }

然而,如果您使用Winforms Web浏览器和winforms主机..您有一个属性“SuppressScriptErrors”将其设置为true

    <WindowsFormsHost Name="WinformsHost" Grid.Row="1">
    <winForms:WebBrowser x:Name="WebBrowserControlView" ScriptErrorsSuppressed="True" AllowWebBrowserDrop="False"></winForms:WebBrowser>
</WindowsFormsHost>

答案 6 :(得分:2)

我在过去遇到过这个问题,最后通过注入一个可以抑制错误处理的Javascript脚本解决了这个问题。希望这也可以帮到你。

Disable Javascript errors in WEbBrowsercontrol

答案 7 :(得分:1)

你可以使用这个技巧

vb.net

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const WM_CLOSE As Short = &H10s

并调用最后一个lib:

 dim hwnd 
    dim vreturnvalue
    hwnd = FindWindow(vbNullString,"script error")
    if hwnd<>0 then vreturnvalue = SendMessage(hwnd, WM_CLOSE,  &O0s, &O0s)

答案 8 :(得分:0)

Wolf5 的回答很好,但 if (objComWebBrowser == null) 似乎不起作用。相反,我检查 WebBrowserIsLoaded 实例:

public void HideScriptErrors(WebBrowser webBrowser)
{
    if (!webBrowser.IsLoaded)
    {
        webBrowser.Loaded += WebBrowser_Loaded; // in case we are too early
        return;
    }

    var objComWebBrowser = typeof(WebBrowser).GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(webBrowser);
    if (objComWebBrowser == null)
    {
        return;
    }

    objComWebBrowser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, null, objComWebBrowser, new object[] { true });
}
private void WebBrowser_Loaded(object sender, RoutedEventArgs e)
{
    var webBrowser = sender as WebBrowser;
    webBrowser.Loaded -= WebBrowser_Loaded;
    HideScriptErrors(webBrowser);
}

在第一次之后还需要删除 Loaded 事件处理程序,因为当通过切换到不同的选项卡使其不可见时,控件可能会被卸载和再次加载多次。此外,当 if (!wb.Loaded)) 在其第一次导航时尚不可见时,WebBrowser 回退仍然很重要,例如如果它位于应用程序启动时不可见的其他选项卡上。