【问题标题】:How to handle WPF WebBrowser control navigation exception如何处理 WPF WebBrowser 控件导航异常
【发布时间】:2012-09-06 12:21:29
【问题描述】:

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

所以WPF WebBrowser control有一个例外。

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

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

我们该如何处理?

谢谢!

附: 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");
     }
}

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

【问题讨论】:

    标签: c# .net wpf


    【解决方案1】:

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

    在没有更好的解决方案的情况下,我连接了 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
                }
            }
        }
    }
    

    【讨论】:

    • 前段时间我在LoadCompleted 事件中添加了类似的代码。但有时doc.url 在生产中会返回空值或空值。所以我认为即使代码在Navigated处理程序中,这种方法也不可靠。
    • AssociatedObject.Document 是什么?我不清楚(我正在使用 WPF,顺便说一句)
    • 我遇到了和@Lu55 一样的问题。发现了我在下面发布的不检查 res://ieframe.dll 的解决方案
    【解决方案2】:

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

    我找到了一个答案 here(在其他地方)建议使用 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 框架上

    【讨论】:

    • 这看起来真不错!太糟糕了,我无法再访问实现我的解决方案的代码库,所以我可以对此进行测试。 :(
    • 看起来很有希望,但它不会从框架内获取用户启动的导航。这些事件仅针对我最初进行的 Navigate() 调用触发。
    【解决方案3】:

    这里也可以使用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
                }
            };
    

    【讨论】:

      【解决方案4】:

      我已经为这个问题苦苦挣扎了一段时间。我发现了一种比接受的答案更干净的方法来处理这个问题。检查 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;
      

      【讨论】:

      • 嗨,伙计!感谢您的回答。我无法检查它。但是通过代码看起来不错。
      猜你喜欢
      • 1970-01-01
      • 2018-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-12
      • 2012-04-01
      • 1970-01-01
      相关资源
      最近更新 更多