回 帖 发 新 帖 刷新版面

主题:请问 SetUnhandledExceptionFilter 在C#中如何调用?

下面是我在网上找到的代码,希望能够截获全局的异常:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace SetUnhandledExceptionFilter
{
    public partial class Form1 : Form
    {


        public delegate Int32 CallBack(ref long a);

        CallBack mycall;

        [DllImport("kernel32")]
        private static extern void RtlMoveMemory(ref byte dst,
        ref byte src, Int32 len);

        [DllImport("kernel32")]
        private static extern Int32 SetUnhandledExceptionFilter(CallBack cb);

        public static Int32 newexceptionfilter(ref long a)
        {
            MessageBox.Show("截获了全局异常!");
            return 0;
        }

        public Form1()
        {
            InitializeComponent();

            mycall = new CallBack(newexceptionfilter);
            SetUnhandledExceptionFilter(mycall);

        }

        private void button1_Click(object sender, EventArgs e)
        {
            byte a = 1, b = 2;
            MessageBox.Show("a=" + a.ToString());
            RtlMoveMemory(ref a, ref b, 200);
            MessageBox.Show("a=" + a.ToString());
        }

    }
}


但是运行后并没起到截获异常的效果:
按预想效果,点击 button1 后,应该弹出一个“截获了全局异常!”这样的对话框。

实际情况是:
当代码RtlMoveMemory(ref a, ref b, int c)中c=200时,程序报错“SetUnhandledExceptionFilter .vshost.exe[2504]中发生未处理的win32异常。”
当c=2000时,程序直接退出,没有任何显示(没有预想的“截获了全局异常!”),请问这是什么原因呢?

回复列表 (共4个回复)

沙发

你直接挂接
Application.ThreadException(仅限WinForms,且只对UI线程有效)
或者
AppDomain.CurrentDomain.UnhandledException
事件

岂不更加方便,还是.net兼容事件

板凳

谢谢你的回复,我选择了第二个方法,在调试的时候这个异常可以被捕获,但是在不调试的时候就不能捕获异常了,请问这是为什么呢?有什么解决方法吗?

我研究一下,这应该是个外部异常,C#如何捕获这样的异常信息呢?

3 楼

我一般采用ThreadException方法,并且一直用的挺好。
AppDomain的那个操作起来比较麻烦,因为同时受.net和操作系统监控,可能最终效果不理想。

另外,不要两个同时使用,只有一个会工作。

这两种处理方法都是在各自领域内工作的,ThreadException会捕获UI线程上的未处理异常,AppDomain.UnhandledException在域内有效
也就是说,后者要比前者低级一些,毕竟WinForms要跑在一个域内

4 楼

我有采纳你的建议,把AppDomain的UnhandledException注释了,但ThreadException却没有捕获异常,不论调试或者未调试都不能,这是什么回事啊?

下面是我修改后的Program.cs:

namespace GPF
{
    static class Program
    {
        /// <summary>
        /// 應用程式的主要進入點。
        /// </summary>
        [STAThread]
        static void Main()
        {

            //AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
            Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(AppThreadException);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Application.Run(new Form1());

        }

        //public static void OnUnhandledException(object o, UnhandledExceptionEventArgs e)
        //{
        //    MessageBox.Show("Trap a Global Error!");
        //    HandleUnhandledException(e.ExceptionObject);
        //}

        public static void AppThreadException(object source, System.Threading.ThreadExceptionEventArgs e)
        {
            MessageBox.Show("Trap a Global Error!");
            HandleUnhandledException(e.Exception);
        }

        private static void HandleUnhandledException(Object o)
        {
            Exception exp = o as Exception;
            MessageBox.Show(exp.Message, "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
            Application.Exit(); // Shutting down
        }
    }
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册