如何处理WPF WebBrowser控件导航异常

10

假设 WPF WebBrowser 控件 显示某些导航错误,并且页面未显示。

因此,WPF WebBrowser 控件 抛出了一个异常。

我在这里找到了一些类似的问题(链接),但那不是我需要的。

实际上,我需要一些方法和对象来获取异常。

我们该如何处理它?

谢谢!

P.S. 对于 WinForm WebBrowser 控件,有一些方法... 我们是否可以对 WPF WebBrowser 控件采取类似的方法?

public Form13()
{
     InitializeComponent();

     this.webBrowser1.Navigate("http://blablablabla.bla");

      SHDocVw.WebBrowser axBrowser = (SHDocVw.WebBrowser)this.webBrowser1.ActiveXInstance;
      axBrowser.NavigateError +=
           new SHDocVw.DWebBrowserEvents2_NavigateErrorEventHandler(axBrowser_NavigateError);
}

void axBrowser_NavigateError(object pDisp, ref object URL,
       ref object Frame, ref object StatusCode, ref bool Cancel)
{
     if (StatusCode.ToString() == "404")
     {
         MessageBox.Show("Page no found");
     }
}

P.S.#2:我认为在WPF应用程序下托管WinForm WebBrowser控件不是一个答案。

4个回答

10

我遇到了类似的问题。当计算机失去互联网连接时,我们希望以一种良好的方式处理它。

在没有更好的解决方案的情况下,我连接了WebBrowser的Navigated事件并查看文档的URL。如果它是res://ieframe.dll,则我相当有信心发生了某些错误。

也许可以查看文档并查看服务器是否返回了404。

private void Navigated(object sender, NavigationEventArgs navigationEventArgs)
{
    var browser = sender as WebBrowser;
    if(browser != null)
    {
        var doc = AssociatedObject.Document as HTMLDocument;
        if (doc != null)
        {
            if (doc.url.StartsWith("res://ieframe.dll"))
            {
                // Do stuff to handle error navigation
            }
        }
    }
}

1
前段时间我将类似的代码放到了“LoadCompleted”事件中。但是在生产环境中,有时候“doc.url”会返回空值或者null。因此,我认为即使代码在“Navigated”处理程序中,这种方法也不可靠。 - Ilya Serbis
1
AssociatedObject.Document 是什么?我不太清楚(顺便说一下,我正在使用 WPF)。 - Jack
我遇到了与@Lu55相同的问题。我发现了一个解决方案,如下所述,它不检查res://ieframe.dll。 - cppguy

7

虽然这个问题有些老旧,但由于我刚刚经历了这个问题,因此我想分享一下。起初,我实现了Markus的解决方案,但是由于我们的防火墙重新映射了403消息页面,我想要更好一点的东西。

我在这里(和其他地方)找到了一个答案,建议使用NavigationService,因为它有一个NavigationFailed事件。

在您的XAML中添加:

<Frame x:Name="frame"/>

在您的代码后端构造函数中添加以下内容:
frame.Navigated += new System.Windows.Navigation.NavigatedEventHandler(frame_Navigated);
frame.NavigationFailed += frame_NavigationFailed;
frame.LoadCompleted += frame_LoadCompleted;

frame.NavigationService.Navigate(new Uri("http://theage.com.au"));

处理程序现在可以处理导航失败或成功的情况:
void frame_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
{
  e.Handled = true;
  // TODO: Goto an error page.
}

private void frame_Navigated(object sender,  System.Windows.Navigation.NavigationEventArgs e)
{
  System.Diagnostics.Trace.WriteLine(e.WebResponse.Headers);
}

顺便说一下:这是在 .Net 4.5 框架上的。


这看起来非常不错!可惜我不再有访问我实现解决方案的代码库的权限,所以无法测试这个。 :( - Markus
看起来很有前途,但它无法捕捉到框架内部用户发起的导航。事件只会对我最初发起的Navigate()调用触发。 - RandomEngy

2

在这里也可以使用dynamic方法。

wb.Navigated += delegate(object sender, NavigationEventArgs args)
        {
            dynamic doc = ((WebBrowser)sender).Document;
            var url = doc.url as string;
            if (url != null && url.StartsWith("res://ieframe.dll"))
            {
                // Do stuff to handle error navigation
            }
        };

1
我曾经为这个问题苦苦挣扎。我发现了一种比接受的答案更简洁的处理方法。检查res://ieframe.dll并不总是对我有效。有时候,当发生导航错误时,文档url为空。

将以下引用添加到您的项目中:

  1. Microsoft.mshtml
  2. Microsoft.VisualStudio.OLE.Interop
  3. SHDocVw(在COM下称为“Microsoft Internet Controls”)

创建以下辅助类:

using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Windows.Controls;
using System.Windows.Navigation;

/// <summary>
/// Adds event handlers to a webbrowser control
/// </summary>
internal class WebBrowserHelper
{
    [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "consistent naming")]
    private static readonly Guid SID_SWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");

    internal WebBrowserHelper(WebBrowser browser)
    {
        // Add event handlers
        browser.Navigated += this.OnNavigated;

        // Navigate to about:blank to setup the browser event handlers in first call to OnNavigated
        browser.Source = null;
    }

    internal delegate void NavigateErrorEvent(string url, int statusCode);

    internal event NavigateErrorEvent NavigateError;

    private void OnNavigated(object sender, NavigationEventArgs e)
    {
        // Grab the browser and document instance
        var browser = sender as WebBrowser;
        var doc = browser?.Document;

        // Check if this is a nav to about:blank
        var aboutBlank = new Uri("about:blank");
        if (aboutBlank.IsBaseOf(e.Uri))
        {
            Guid serviceGuid = SID_SWebBrowserApp;
            Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;

            IntPtr obj = IntPtr.Zero;
            var serviceProvider = doc as Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
            if (serviceProvider?.QueryService(ref serviceGuid, ref iid, out obj) == 0)
            {
                // Set up event handlers
                var webBrowser2 = Marshal.GetObjectForIUnknown(obj) as SHDocVw.IWebBrowser2;
                var webBrowserEvents2 = webBrowser2 as SHDocVw.DWebBrowserEvents2_Event;
                if (webBrowserEvents2 != null)
                {
                    // Add event handler for navigation error
                    webBrowserEvents2.NavigateError -= this.OnNavigateError;
                    webBrowserEvents2.NavigateError += this.OnNavigateError;
                }
            }
        }
    }

    /// <summary>
    /// Invoked when navigation fails
    /// </summary>
    [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "consistent naming")]
    [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:FieldNamesMustBeginWithLowerCaseLetter", Justification = "consistent naming")]
    private void OnNavigateError(object pDisp, ref object URL, ref object Frame, ref object StatusCode, ref bool Cancel)
    {
        this.NavigateError.Invoke(URL as string, (int)StatusCode);
    }
}

然后在你的窗口类中:
// Init the UI
this.InitializeComponent();
this.WebBrowserHelper = new WebBrowserHelper(this.MyBrowserPane);

// Handle nav error
this.WebBrowserHelper.NavigateError += this.OnNavigateError;

嗨,伙计!谢谢回答。我还没来得及检查它,但代码看起来没问题。 - NoWar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接