How to handle WPF WebBrowser control navigation exception

前端 未结 4 1828
慢半拍i
慢半拍i 2020-12-11 16:13

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

So there is an exception of WPF WebBrowser contro

相关标签:
4条回答
  • 2020-12-11 16:53

    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.

    I found an answer here (amongst other places) that suggests using NavigationService as it has a NavigationFailed event.

    In your XAML, add:

    <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

    0 讨论(0)
  • 2020-12-11 16:54

    It is also possible to use dynamic approach here.

    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
                }
            };
    
    0 讨论(0)
  • 2020-12-11 16:54

    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.dll didn't always work for me. Sometimes the document url is null when a navigation error happened.

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

    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;
    
    0 讨论(0)
  • 2020-12-11 16:58

    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.

    Maybe it is possible to look at the document and see if a server returned 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
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题