Application.ThreadException 获取的 Win32Exception 类型不正确

Application.ThreadException is getting incorrect Win32Exception type

我们有一个非常复杂的应用程序,它有一个在启动时初始化的 ThreadException 处理程序,应用程序抛出的任何未立即处理的异常都由这个 ThreadException 处理程序以统一的方式处理。

这大部分工作...但是我们有几个自定义异常类型,我们想用这个异常处理程序来处理,并且由于某些原因,这些异常类型总是在 ThreadException 处理程序中显示为 System.ComponentModel .Win32Exception 类型,而不是我们的自定义类型。

我已经尝试了所有我能想到的故障排除方法,包括确保我们的自定义异常 classes 实现了所有推荐的构造函数,包括序列化构造函数。

其他信息...当我创建一个仅包含来自现有异常的消息的新异常时,它以 System.Exception 的形式出现。例如:

                MSCSqlException msx = new MSCSqlException(sqlQuery, sqlParams, sqlException);
                throw new Exception(ex.Message);

工作正常并作为 System.Exception.

在异常处理程序中被捕获

但是,如果我尝试类似的操作:

                MSCSqlException msx = new MSCSqlException(sqlQuery, sqlParams, sqlException);
                throw new Exception(ex.Message, ex);

然后异常管理器捕获上面的 System.ComponentModel.Win32Exception 而不仅仅是 System.Exception.

为了完整起见,我想做的是:

                throw new MSCSqlException(sqlQuery, sqlParams, sqlException);

并让 Application.ThreadException 处理程序接收正确类型的 MSCSqlException。

有什么办法解决这个问题吗? Application.ThreadException 是否有一些与自定义错误类型相关的怪癖?

我们的自定义异常class:

[Serializable]
public class MSCSqlException : Exception
{
    public string SqlCommand { get; private set; }
    public object[] SqlParameters { get; private set; }

    public MSCSqlException()
    {
    }

    public MSCSqlException(string message)
        : base(message)
    {
    }

    public MSCSqlException(string message, Exception inner) : base(message, inner)
    {
    }

    public MSCSqlException(string command, object[] parameters, SqlException sx) : base(CreateUsefulMessage(sx, command, parameters), sx)
    {
        SqlCommand = command;
        SqlParameters = parameters;
    }

    protected MSCSqlException(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        SqlCommand = info.GetString("SqlCommand");
    }

    [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (info == null)
        {
            throw new ArgumentNullException("info");
        }

        info.AddValue("SqlCommand", SqlCommand);
        base.GetObjectData(info, context);
    }

    public static string CreateUsefulMessage(SqlException sx, string sqlCommand, object[] sqlParameters)
    {
        string message = sx.Message + Environment.NewLine;

        if(sqlParameters != null && sqlParameters.Count() > 0)
        {
            message = message + "Parameters:" + Environment.NewLine;
            foreach(object sp in sqlParameters)
            {
                message = message + "\t" + sp.ToString() + Environment.NewLine;
            }
        }

        message = message + "SQL Statement:" + Environment.NewLine;
        message = message + sqlCommand;

        return message;
    }
}

我们终于弄明白了...问题是 .Net 如何处理后台工作程序 Completed 事件中抛出的异常的错误或功能。无论出于何种原因,在这种情况下,.Net 运行 时间似乎将最内层异常从堆栈跟踪传递到 ThreadException 处理程序,而不是预期的最外层异常。当抛出 SQLException 时,这个最里面的异常是 Win32Exception。

这里有更多信息: