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。
这里有更多信息:
我们有一个非常复杂的应用程序,它有一个在启动时初始化的 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。
这里有更多信息: