问题 WebBrowser控件页面加载错误


我的winform上有WebBrowser控件。当我尝试导航到一些网站时,我得到标准的IE错误页面,如:

  • “导航到网页已被取消”
  • “地址无效”
  • “页面无法加载”
  • 等等

我需要处理这些错误并将自定义错误消息返回给用户。有什么方法可以解决这个问题吗?


10016
2017-11-19 08:31


起源



答案:


您想要处理NavigateError事件,如图所示 这里

编辑:包括链接中的示例代码:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Security.Permissions;

namespace WebBrowserExtensibility
{
    [PermissionSetAttribute(SecurityAction.Demand, Name="FullTrust")]
    public class Form1 : Form
    {
        [STAThread]
        public static void Main()
        {
            Application.Run(new Form1());
        }

        private WebBrowser2 wb = new WebBrowser2();
        public Form1()
        {
            wb.Dock = DockStyle.Fill;
            wb.NavigateError += new 
                WebBrowserNavigateErrorEventHandler(wb_NavigateError);
            Controls.Add(wb);

            // Attempt to navigate to an invalid address.
            wb.Navigate("www.widgets.microsoft.com");
        }

        private void wb_NavigateError(
            object sender, WebBrowserNavigateErrorEventArgs e)
        {
            // Display an error message to the user.
            MessageBox.Show("Cannot navigate to " + e.Url);
        }
    }

    public class WebBrowser2 : WebBrowser
    {
        AxHost.ConnectionPointCookie cookie;
        WebBrowser2EventHelper helper;

        [PermissionSetAttribute(SecurityAction.LinkDemand, Name="FullTrust")]
        protected override void CreateSink()
        {
            base.CreateSink();

            // Create an instance of the client that will handle the event
            // and associate it with the underlying ActiveX control.
            helper = new WebBrowser2EventHelper(this);
            cookie = new AxHost.ConnectionPointCookie(
                this.ActiveXInstance, helper, typeof(DWebBrowserEvents2));
        }

        [PermissionSetAttribute(SecurityAction.LinkDemand, Name="FullTrust")]
        protected override void DetachSink()
        {
            // Disconnect the client that handles the event
            // from the underlying ActiveX control.
            if (cookie != null)
            {
                cookie.Disconnect();
                cookie = null;
            }
            base.DetachSink();
        }

        public event WebBrowserNavigateErrorEventHandler NavigateError;

        // Raises the NavigateError event.
        protected virtual void OnNavigateError(
            WebBrowserNavigateErrorEventArgs e)
        {
            if (this.NavigateError != null)
            {
                this.NavigateError(this, e);
            }
        }

        // Handles the NavigateError event from the underlying ActiveX 
        // control by raising the NavigateError event defined in this class.
        private class WebBrowser2EventHelper : 
            StandardOleMarshalObject, DWebBrowserEvents2
        {
            private WebBrowser2 parent;

            public WebBrowser2EventHelper(WebBrowser2 parent)
            {
                this.parent = parent;
            }

            public void NavigateError(object pDisp, ref object url, 
                ref object frame, ref object statusCode, ref bool cancel)
            {
                // Raise the NavigateError event.
                this.parent.OnNavigateError(
                    new WebBrowserNavigateErrorEventArgs(
                    (String)url, (String)frame, (Int32)statusCode, cancel));
            }
        }
    }

    // Represents the method that will handle the WebBrowser2.NavigateError event.
    public delegate void WebBrowserNavigateErrorEventHandler(object sender, 
        WebBrowserNavigateErrorEventArgs e);

    // Provides data for the WebBrowser2.NavigateError event.
    public class WebBrowserNavigateErrorEventArgs : EventArgs
    {
        private String urlValue;
        private String frameValue;
        private Int32 statusCodeValue;
        private Boolean cancelValue;

        public WebBrowserNavigateErrorEventArgs(
            String url, String frame, Int32 statusCode, Boolean cancel)
        {
            urlValue = url;
            frameValue = frame;
            statusCodeValue = statusCode;
            cancelValue = cancel;
        }

        public String Url
        {
            get { return urlValue; }
            set { urlValue = value; }
        }

        public String Frame
        {
            get { return frameValue; }
            set { frameValue = value; }
        }

        public Int32 StatusCode
        {
            get { return statusCodeValue; }
            set { statusCodeValue = value; }
        }

        public Boolean Cancel
        {
            get { return cancelValue; }
            set { cancelValue = value; }
        }
    }

    // Imports the NavigateError method from the OLE DWebBrowserEvents2 
    // interface. 
    [ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
    TypeLibType(TypeLibTypeFlags.FHidden)]
    public interface DWebBrowserEvents2
    {
        [DispId(271)]
        void NavigateError(
            [In, MarshalAs(UnmanagedType.IDispatch)] object pDisp,
            [In] ref object URL, [In] ref object frame, 
            [In] ref object statusCode, [In, Out] ref bool cancel);
    }
}

11
2017-11-19 12:51



我将阅读示例并使用它。谢谢。还有另一个问题。当用户尝试导航到文件链接时(当用户尝试下载文件时)我需要处理这种情况 - 我应该拒绝这样的请求。这种情况也可以处理吗? - Akim Khalilov
如果您还处理Navigate事件,则可以检查URL(这将是文件名),并将WebBrowserNavigatingEventArgs的Cancel属性设置为true(如果它是文件而不是页面)。但这取决于能否区分文件下载和常规导航。 - stuartd
好吧,我可以检查我的代码中的大多数文件扩展名(如果uri包含文件名)。但是有很多例子可以说服务器可以使用某些流进行响应,这可以通过浏览器检测,如二进制数据和打开/保存/取消消息框。我可以在它向用户显示之前捕获此消息框吗? - Akim Khalilov
在决定是否启动下载时,控件会查看Content-Type和Content-Disposition标头:BeforeNavigate2方法可让您查看这些 - 请参阅 msdn.microsoft.com/en-us/library/ms775148%28VS.85%29.aspx 了解更多信息 - stuartd
关于NavigateError的几句话。我可以显示一些消息,或者从我的代码中执行其他逻辑。但是我如何能够将标准错误消息页面“此程序无法显示网页”替换为我的自定义?可能是我可以隐藏这个用户,但是怎么样? - Akim Khalilov


答案:


您想要处理NavigateError事件,如图所示 这里

编辑:包括链接中的示例代码:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Security.Permissions;

namespace WebBrowserExtensibility
{
    [PermissionSetAttribute(SecurityAction.Demand, Name="FullTrust")]
    public class Form1 : Form
    {
        [STAThread]
        public static void Main()
        {
            Application.Run(new Form1());
        }

        private WebBrowser2 wb = new WebBrowser2();
        public Form1()
        {
            wb.Dock = DockStyle.Fill;
            wb.NavigateError += new 
                WebBrowserNavigateErrorEventHandler(wb_NavigateError);
            Controls.Add(wb);

            // Attempt to navigate to an invalid address.
            wb.Navigate("www.widgets.microsoft.com");
        }

        private void wb_NavigateError(
            object sender, WebBrowserNavigateErrorEventArgs e)
        {
            // Display an error message to the user.
            MessageBox.Show("Cannot navigate to " + e.Url);
        }
    }

    public class WebBrowser2 : WebBrowser
    {
        AxHost.ConnectionPointCookie cookie;
        WebBrowser2EventHelper helper;

        [PermissionSetAttribute(SecurityAction.LinkDemand, Name="FullTrust")]
        protected override void CreateSink()
        {
            base.CreateSink();

            // Create an instance of the client that will handle the event
            // and associate it with the underlying ActiveX control.
            helper = new WebBrowser2EventHelper(this);
            cookie = new AxHost.ConnectionPointCookie(
                this.ActiveXInstance, helper, typeof(DWebBrowserEvents2));
        }

        [PermissionSetAttribute(SecurityAction.LinkDemand, Name="FullTrust")]
        protected override void DetachSink()
        {
            // Disconnect the client that handles the event
            // from the underlying ActiveX control.
            if (cookie != null)
            {
                cookie.Disconnect();
                cookie = null;
            }
            base.DetachSink();
        }

        public event WebBrowserNavigateErrorEventHandler NavigateError;

        // Raises the NavigateError event.
        protected virtual void OnNavigateError(
            WebBrowserNavigateErrorEventArgs e)
        {
            if (this.NavigateError != null)
            {
                this.NavigateError(this, e);
            }
        }

        // Handles the NavigateError event from the underlying ActiveX 
        // control by raising the NavigateError event defined in this class.
        private class WebBrowser2EventHelper : 
            StandardOleMarshalObject, DWebBrowserEvents2
        {
            private WebBrowser2 parent;

            public WebBrowser2EventHelper(WebBrowser2 parent)
            {
                this.parent = parent;
            }

            public void NavigateError(object pDisp, ref object url, 
                ref object frame, ref object statusCode, ref bool cancel)
            {
                // Raise the NavigateError event.
                this.parent.OnNavigateError(
                    new WebBrowserNavigateErrorEventArgs(
                    (String)url, (String)frame, (Int32)statusCode, cancel));
            }
        }
    }

    // Represents the method that will handle the WebBrowser2.NavigateError event.
    public delegate void WebBrowserNavigateErrorEventHandler(object sender, 
        WebBrowserNavigateErrorEventArgs e);

    // Provides data for the WebBrowser2.NavigateError event.
    public class WebBrowserNavigateErrorEventArgs : EventArgs
    {
        private String urlValue;
        private String frameValue;
        private Int32 statusCodeValue;
        private Boolean cancelValue;

        public WebBrowserNavigateErrorEventArgs(
            String url, String frame, Int32 statusCode, Boolean cancel)
        {
            urlValue = url;
            frameValue = frame;
            statusCodeValue = statusCode;
            cancelValue = cancel;
        }

        public String Url
        {
            get { return urlValue; }
            set { urlValue = value; }
        }

        public String Frame
        {
            get { return frameValue; }
            set { frameValue = value; }
        }

        public Int32 StatusCode
        {
            get { return statusCodeValue; }
            set { statusCodeValue = value; }
        }

        public Boolean Cancel
        {
            get { return cancelValue; }
            set { cancelValue = value; }
        }
    }

    // Imports the NavigateError method from the OLE DWebBrowserEvents2 
    // interface. 
    [ComImport, Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
    TypeLibType(TypeLibTypeFlags.FHidden)]
    public interface DWebBrowserEvents2
    {
        [DispId(271)]
        void NavigateError(
            [In, MarshalAs(UnmanagedType.IDispatch)] object pDisp,
            [In] ref object URL, [In] ref object frame, 
            [In] ref object statusCode, [In, Out] ref bool cancel);
    }
}

11
2017-11-19 12:51



我将阅读示例并使用它。谢谢。还有另一个问题。当用户尝试导航到文件链接时(当用户尝试下载文件时)我需要处理这种情况 - 我应该拒绝这样的请求。这种情况也可以处理吗? - Akim Khalilov
如果您还处理Navigate事件,则可以检查URL(这将是文件名),并将WebBrowserNavigatingEventArgs的Cancel属性设置为true(如果它是文件而不是页面)。但这取决于能否区分文件下载和常规导航。 - stuartd
好吧,我可以检查我的代码中的大多数文件扩展名(如果uri包含文件名)。但是有很多例子可以说服务器可以使用某些流进行响应,这可以通过浏览器检测,如二进制数据和打开/保存/取消消息框。我可以在它向用户显示之前捕获此消息框吗? - Akim Khalilov
在决定是否启动下载时,控件会查看Content-Type和Content-Disposition标头:BeforeNavigate2方法可让您查看这些 - 请参阅 msdn.microsoft.com/en-us/library/ms775148%28VS.85%29.aspx 了解更多信息 - stuartd
关于NavigateError的几句话。我可以显示一些消息,或者从我的代码中执行其他逻辑。但是我如何能够将标准错误消息页面“此程序无法显示网页”替换为我的自定义?可能是我可以隐藏这个用户,但是怎么样? - Akim Khalilov