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

时间:2017-03-29 22:46:48

标签: c# winforms exception-handling custom-exceptions thread-exceptions

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

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

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

附加信息...当我仅使用来自现有异常的消息创建新异常时,这将作为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错误?

我们的自定义异常类:

[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;
    }
}

1 个答案:

答案 0 :(得分:0)

我们终于弄清楚了......问题是.Net如何处理后台工作者已完成事件中引发的异常的错误或特征。无论出于何种原因,在这种情况下,.Net运行时似乎将最内层的异常从堆栈跟踪传递给ThreadException处理程序而不是预期的最外层异常。抛出SQLException时,这个最内部的异常是Win32Exception。

有关这方面的更多信息:

Application.ThreadException is getting incorrect Win32Exception type