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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12300025/
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-09-13 05:14:20  来源:igfitidea点击:

How to handle WPF WebBrowser control navigation exception

c#.netwpf

提问by Developer

Let's say that WPF WebBrowser controlshows some navigation errors and the page is not showing.

假设WPF WebBrowser control显示了一些导航错误并且页面没有显示。

So there is an exception of WPF WebBrowser control.

所以有一个例外WPF WebBrowser control

I found some similar questions herebut it is not what I need.

我在这里发现了一些类似的问题但这不是我需要的。

In fact, I need some method and object that has an exception to get it somehow.

事实上,我需要一些有异常的方法和对象才能以某种方式获取它。

How do we can handle it?

我们该如何处理?

Thank you!

谢谢!

P.S. There is some approach for WinForm WebBrowser Control... Can we do something similar to WPF WebBrowsercontrol?

PS有一些WinForm WebBrowser Control的方法......我们可以做一些类似于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 To host WinForm WebBrowser control under WPF App is not an answer I think.

PS #2 在 WPF App 下托管 WinForm WebBrowser 控件不是我认为的答案。

采纳答案by Markus

I'm struggling with a similar problem. When the computer loses internet connection we want to handle that in a nice way.

我正在努力解决类似的问题。当计算机失去互联网连接时,我们希望以一种很好的方式处理它。

In the lack of a better solution, I hooked up the Navigated event of the WebBrowser and look at the URL for the document. If it is res://ieframe.dll I'm pretty confident that some error has occurred.

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

Maybe it is possible to look at the document and see if a server returned 404.

也许可以查看文档,看看服务器是否返回了 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
            }
        }
    }
}

回答by dave

It's an old question but since I have just suffered through this, I thought I may as well share. First, I implemented Markus' solution but wanted something a bit better as our Firewall remaps 403 message pages.

这是一个老问题,但由于我刚刚经历过这个问题,我想我也可以分享一下。首先,我实施了 Markus 的解决方案,但想要更好一些,因为我们的防火墙重新映射了 403 消息页面。

I found an answer here(amongst other places) that suggests using NavigationServiceas it has a NavigationFailedevent.

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

In your XAML, add:

在您的 XAML 中,添加:

<Frame x:Name="frame"/>

In your code-behind's constructor, add:

在代码隐藏的构造函数中,添加:

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

The handlers can now deal with either a failed navigation or a successful one:

处理程序现在可以处理失败的导航或成功的导航:

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

BTW: This is on the .Net 4.5 framework

顺便说一句:这是在 .Net 4.5 框架上

回答by Maxim

It is also possible to use dynamicapproach here.

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

回答by cppguy

I'd been struggling with this issue for some time. I discovered a cleaner way to handle this than the accepted answer. Checking for res://ieframe.dlldidn't always work for me. Sometimes the document url is null when a navigation error happened.

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

Add the following References to you project:

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

  1. Microsoft.mshtml
  2. Microsoft.VisualStudio.OLE.Interop
  3. SHDocVw(Under COM it's called "Microsoft Internet Controls")
  1. 微软.mshtml
  2. Microsoft.VisualStudio.OLE.Interop
  3. SHDocVw(在 COM 下称为“Microsoft Internet Controls”)

Create the following helper class:

创建以下帮助类:

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

Then in your window class:

然后在您的窗口类中:

// Init the UI
this.InitializeComponent();
this.WebBrowserHelper = new WebBrowserHelper(this.MyBrowserPane);

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