抛出异常,但保留堆栈跟踪

本文关键字:堆栈 跟踪 保留 抛出异常 | 更新日期: 2023-09-27 18:07:49

我想抛出一个异常,但自定义消息和持久化堆栈跟踪太。我已经查过了各种线索。

catch (Exception ex)
{
throw; // Message is read only but stacktrace persist
throw ex; // Message is readonly and strack trace also blows .. worst!
throw new CustomException("My exception");// Message can be overridden but stacktrace lost
throw new CustomException("My message",ex);// same as above. However if this constructor in exception class calls same constructor of base class then .. see below
}

当使用last方法时(使用自定义异常构造函数调用基类构造函数),死亡屏幕上的输出类似于:

**The remote server returned an error: (401) Unauthorized.**
[WebException: The remote server returned an error: (401) Unauthorized.]
original stack trace 
[NewException: newMessage]
New  Stack Trace

好在所有的东西都在屏幕上。但是,在上面,我希望我的异常显示i.e.。"新消息"而不是原始消息。

因此调和我的问题:我如何在死亡屏幕上显示原始堆栈跟踪,但带有自定义错误消息?

抛出异常,但保留堆栈跟踪

 throw new CustomException("My message",ex);// same as above (... stacktrace lost)

你在评论中的结论是错误的。堆栈跟踪保存在内部异常中。标准报告(包括Exception.ToString())将报告完整的堆栈跟踪。这就是构造函数正确时所看到的结果。(总是调用正确的基函数!)

但是我不认识[WebException]。在WCF中,需要

  <serviceDebug includeExceptionDetailInFaults="true"/>   

我猜您的Web环境具有类似的功能,可以抑制向客户端的错误信息。

使用第四种方法通常是这样做的,并且是已建立的模式。你不应该将异常处理(或引发)与它们的显示或记录方式或其他方式混淆。

如果你有(捕获的)异常的输出在控制之下,即可以改变/编写相应的代码,你可以简单地使用Exception.ToString()方法,它将打印外部异常,包括所有的"内部"异常。

备注:有时,应用程序不会有意地显示内部异常。例如,在WCF (Windows通信基础)内部异常甚至不从服务器转移到客户端,除非IncludeExceptionDetails(通过配置,代码,…)设置。这通常是因为内部异常被认为是一个实现细节,它可能为攻击者提供有价值的信息来破坏您的应用程序。

如何重写StackTrace属性?

class CustomException : Exception {
    public CustomException(string message, Exception inner) : base(message, inner) {
    }
    public override string StackTrace {
        get {
            if (InnerException != null) {
                return InnerException.StackTrace;
            }
            return base.StackTrace;
        }
    }
}

我同意,选项4通常是最好的…

然而,在开发过程中,我发现将整个catch子句放在#if (!DEBUG)中非常有用,在它外面有一个finally(允许在调试模式下编译):

#if (!DEBUG)
catch (Exception ex)
{
    // Catch logic for Release mode
}
#endif
finally { }

这使得API在错误发生的地方中断,而不是在顶层。

不要养成#if…的习惯。在几乎所有其他情况下,使用

[Conditional("DEBUG")]

代替