70

我有以下代码:

catch(Exception ex)
{
    throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}

不幸的是,这只是吞噬了异常。我可以通过执行以下操作来解决此问题:

catch(Exception ex)
{
    throw;
}

但我仍然想包含自定义消息以获取事件记录的帮助。

如何在不丢失任何信息的情况下将此消息添加到异常中?(堆栈跟踪/调试符号等)

4

4 回答 4

97

如果您只需要向原始异常添加信息,例如用户可读的消息或对您跟踪错误有用但对最终用户无用的特定详细信息,您可以使用Exception 的Data属性,它是一个键/值对字典。

我们广泛使用它来记录信息,例如正在执行的报告或正在处理的文件,以便操作可以确定错误发生时究竟发生了什么。用户不需要此详细信息,因为他们直接处理失败的原因。

您还可以使用它来传递对用户有意义的纯文本消息。唯一的问题是您必须在日志框架或最终用户界面中执行一些额外的工作,以便提取数据并使其对消费者有用。

例如,您可以这样做:

catch (Exception ex)
{
    ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file.");
    throw;
}

然后在客户端代码中,您可以测试 UserMessage 是否存在,如果存在,则将其呈现给用户而不是 Exception:

catch (Exception ex)
{
    if (ex.Data.Contains("UserMessage"))
    {
        MessageBox.Show(ex.Data["UserMessage"].ToString());
    }
    else
    {
        MessageBox.Show(ex.Message);
    }
}
于 2013-01-19T01:28:02.697 回答
17

原来的异常仍然存在。

当您进行异常日志记录时,您收到的异常将是您使用消息生成的 FatalException。原始异常位于ex.InnerException. 您可以继续循环 InnerException 直到它为 null 以获取所有 Stack Trace 信息等。

于 2013-01-19T01:00:16.050 回答
2

简而言之,不要。

我相信您可以通过一些反思找到解决此问题的方法,但我强烈警告您不要这样做。它违背了 .NET 中异常的原始设计。异常不仅有助于记录,它们还提供有关应用程序失败的原始原因的信息。

通常首选使用第一个选项,因为它维护原始异常的堆栈跟踪,但允许您通过将其包装在单独的异常中来提供附加信息。在我自己的代码中,每当我记录异常时,我的记录函数都会通过 InnerException 属性进行递归,以查找有关该错误的所有可能有用信息。

于 2013-01-19T01:07:13.013 回答
0

以防万一有人需要一个好的答案。关键是使用 AppDomain.CurrentDomain.FirstChanceException

您可以使用 IDisposable 创建一个自定义对象以将所有信息放入其中。如果发生异常,则 FirstChanceException 处理程序获取该信息并填充 Exception.Data。

使用本地线程存储使其线程安全。然后,捕获它的代码将获取数据并记录下来。

例子:

using(MyCustomMessage.EnterToLocalStorage("Info for logging"") ) 
{ 
...code 
...exception thrown
.... FirstChanceException examines local thread storage and get's "info for logging" and puts into Exception.Data. 
} 
//Dispose is called and all messages that were put into LocalStorage are removed. 
//So if exception was not thrown before then it like nothing happened.

谷歌 AsyncDiagnosticStack 就是一个很好的例子。https://github.com/StephenCleary/AsyncDiagnostics/blob/master/src/Nito.AsyncEx.AsyncDiagnostics/AsyncDiagnosticStack.cs

于 2019-10-05T04:56:42.717 回答