抛出异常但保持堆栈跟踪

时间:2011-09-06 11:22:49

标签: c# exception

我想抛出一个异常,但是也有自定义消息和persist stacktrace。我经历过各种各样的话题。

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
}

当使用最后一个appraoch时(使用自定义异常构造函数调用基类构造函数),死亡屏幕上的输出类似于:

**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

好的是屏幕上的一切都在那里。但是,最重要的是我希望我的例外显示“新消息”,而不是原始消息。

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

4 个答案:

答案 0 :(得分:8)

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

最后一条评论中的结论是错误的。堆栈跟踪保留在内部异常中。标准报告(包括Exception.ToString())将报告完整的堆栈跟踪。当你获得正确的构造函数时,这就是你所看到的。 (始终打电话给正确的基地!)。

但我不承认[WebException]。在WCF中,您需要

  <serviceDebug includeExceptionDetailInFaults="true"/>   

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

答案 1 :(得分:3)

使用您的第四种方法是如何完成它和已建立的模式。您不应该将异常处理(或提升)与它们的显示或记录方式或其他方式混淆。

如果您控制(捕获)异常的输出,即可以更改/写入相应的代码,您可以简单地使用Exception.ToString()方法,这将打印外部异常,包括所有“内部”的。

注: 有时,应用程序不会故意显示内部异常。例如,在WCF(Windows Communication Foundation)中,除非设置IncludeExceptionDetails(通过配置,代码,...),否则内部异常甚至不会从服务器传输到客户端。这通常是因为内部异常被视为实现细节,这可能为攻击者提供有价值的信息来破坏您的应用程序。

答案 2 :(得分:0)

覆盖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;
        }
    }
}

答案 3 :(得分:0)

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

然而,在开发过程中,我发现将整个catch子句放在#if(!DEBUG)中,并且最后在它之外(允许在Debug模式下编译)非常有用:

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

这会使API在发生错误的位置中断,而不是在顶层。

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

[Conditional("DEBUG")]

在方法前面