异常:如何获取尽可能多的信息?

5
我有一个企业应用程序,每当发生异常时都会记录异常信息。该应用程序是C#和C++.net的组合。
我想尽可能地获得异常时的信息。截至目前,我们只打印出消息和堆栈跟踪(在调试版本中给出行号,但在发布版本中不提供)。
任何错误日志的目标都是尽其所能地指出错误(尽可能接近)。我想知道如何进一步实现这一点?我想要更多的信息。
例如,我知道NullReferenceExceptions和InvalidArguementExceptions包含不同数量的信息,但除了'Message'字段外,我没有利用任何信息。
最好的方法是使用反射并捕获所有公共成员并将其打印出来吗?或者通过链接大量类型检查和强制转换来清晰地打印它们?作为限制条件,我的日志函数只需接受Exception类型的参数。

3
对异常对象调用ToString()通常已经满足我的需求。这会给我异常类型、消息和堆栈跟踪信息。 - cdhowie
这些东西都很有用,但是我遇到了一个问题,在一个非常大规模的算法中出现了空引用异常。在这种情况下,空引用异常包含抛出异常的变量的数据类型,获取这些信息将非常有帮助! - greggorob64
我目前不关心处理和恢复异常。现在我只是尝试优化我们的异常记录器以包含更多信息。 - greggorob64
3
你是否会遍历内部异常并在记录异常本身时做出注释,以便获得尽可能多的信息? - James
@James,不,我没有。那是个好主意。 - greggorob64
3个回答

11

一般来说,答案是记录 ex.ToString()。通常情况下,对象的ToString方法可以显示对象想让你知道的信息。对于基类 Exception 类,这包括消息和堆栈跟踪,以及任何 InnerException 实例的相同信息。特定派生类的异常可能会显示更多信息。

有些异常,如 SqlException 还会捕获其他信息(例如存储过程名称和行号)。在这些情况下,将整个异常序列化并将其保存为 XML 格式在日志数据库中是有帮助的。请注意,并非所有异常类都可以序列化,因此请准备好放弃 XML 部分。

此外,如果你只是记录异常,那么你可能需要重新抛出异常,以便更高层次的代码有机会处理它。当然,如果你已经处于“顶层”,那么就不适用了。


6

请试一下:

try 
{
    //...
}
catch(Exception ex)
{
    Messagebox.Show(ex.ToString());
}

它显示了许多信息,包括所有异常的异常类型消息堆栈跟踪(按顺序排列的所有异常的InnerException)。
更多信息请参见MSDN

1
ex.ToString() 提供了非常多的信息,除非有人在专门的类中重写了 ToString 方法并忘记在其覆盖中提供所有信息。 - Jeppe Stig Nielsen
3
为什么会有负分投票?ex.ToString() 是获取异常想让你知道的所有信息的正确方法吗? - John Saunders

0
        private static string ErrorManager(Exception ex, bool ShowPopUp, bool CrashProgram)
    {
        string stack = ex.StackTrace;
        string source = ex.Source;
        string message = ex.Message;
        string LF = Environment.NewLine;

        string Error = $"A crash happen at {DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss.ff", CultureInfo.InvariantCulture)}{LF}" +
                       $"This is what crashed: {source}{LF}" +
                       $"This is the error message : {LF}{message}{LF + LF}" +
                       $"These are the last instructions executed before the crash : {LF}{stack}{LF + LF}";

        if (ex.InnerException != null)
        {
            Error += $"Inner Exception : {LF}{ex.InnerException.Message}";
        }

        if (ShowPopUp)
        {
            MessageBox.Show(Error, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }

        if (CrashProgram)
        {
            throw new Exception(Error);
        }
        return Error.Trim();
    }

1
为了得到一个有用的答案,这个回应需要被扩展。解释为什么这是一个问题的答案。 - Jeroen Heier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接