什么是展示我的全部的正确方法InnerException
。
我发现我的一些InnerExceptions还有另一个InnerException
,而且还很深入。
会InnerException.ToString()
做的工作,我还是我通过需要循环InnerExceptions
,建立一个String
有StringBuilder
?
什么是展示我的全部的正确方法InnerException
。
我发现我的一些InnerExceptions还有另一个InnerException
,而且还很深入。
会InnerException.ToString()
做的工作,我还是我通过需要循环InnerExceptions
,建立一个String
有StringBuilder
?
Answers:
您可以简单地打印exception.ToString()
-还将包括所有嵌套InnerException
s的全文。
ToString
为内部异常调用自定义方法,如为何System.Exception.ToString不为内部异常调用虚拟ToString所述。。
只需使用 exception.ToString()
http://msdn.microsoft.com/zh-CN/library/system.exception.tostring.aspx
ToString的默认实现获取引发当前异常的类的名称,消息,在内部异常上调用ToString的结果以及调用Environment.StackTrace的结果。如果这些成员中的任何一个为null,则其值不包含在返回的字符串中。
如果没有错误消息,或者它是一个空字符串(“”),则不会返回任何错误消息。内部异常的名称和堆栈跟踪仅在它们不为null时返回。
exception.ToString()还将在该异常的内部异常上调用.ToString(),依此类推...
我通常这样做是为了消除大部分噪音:
void LogException(Exception error) {
Exception realerror = error;
while (realerror.InnerException != null)
realerror = realerror.InnerException;
Console.WriteLine(realerror.ToString())
}
编辑:我忘了这个答案,很惊讶没有人指出你可以做
void LogException(Exception error) {
Console.WriteLine(error.GetBaseException().ToString())
}
error.GetBaseException()
。我相信这样做也一样...
当您需要详细信息(所有消息和堆栈跟踪)以及推荐的详细信息时,@ Jon的答案是最佳解决方案。
但是,在某些情况下,可能只需要内部消息,对于这些情况,我使用以下扩展方法:
public static class ExceptionExtensions
{
public static string GetFullMessage(this Exception ex)
{
return ex.InnerException == null
? ex.Message
: ex.Message + " --> " + ex.InnerException.GetFullMessage();
}
}
当我有不同的侦听器进行跟踪和记录并想对它们有不同的视图时,我经常使用此方法。这样,我可以拥有一个侦听器,该侦听器通过该方法将带有堆栈跟踪的整个错误通过电子邮件发送给开发团队,以使用该.ToString()
方法进行调试;还有一个侦听器,该日志将记录每天发生的所有错误的历史记录而无需使用堆栈跟踪的日志文件。的.GetFullMessage()
方法。
ex
为a AggregateException
,则此输出中将不包含任何内部异常
要仅打印Message
深度异常的一部分,您可以执行以下操作:
public static string ToFormattedString(this Exception exception)
{
IEnumerable<string> messages = exception
.GetAllExceptions()
.Where(e => !String.IsNullOrWhiteSpace(e.Message))
.Select(e => e.Message.Trim());
string flattened = String.Join(Environment.NewLine, messages); // <-- the separator here
return flattened;
}
public static IEnumerable<Exception> GetAllExceptions(this Exception exception)
{
yield return exception;
if (exception is AggregateException aggrEx)
{
foreach (Exception innerEx in aggrEx.InnerExceptions.SelectMany(e => e.GetAllExceptions()))
{
yield return innerEx;
}
}
else if (exception.InnerException != null)
{
foreach (Exception innerEx in exception.InnerException.GetAllExceptions())
{
yield return innerEx;
}
}
}
递归地遍历所有内部异常(包括AggregateException
s 的情况)以打印Message
包含在其中的所有属性,并以换行符分隔。
例如
var outerAggrEx = new AggregateException(
"Outer aggr ex occurred.",
new AggregateException("Inner aggr ex.", new FormatException("Number isn't in correct format.")),
new IOException("Unauthorized file access.", new SecurityException("Not administrator.")));
Console.WriteLine(outerAggrEx.ToFormattedString());
发生外部聚集。
内部aggr前。
数字格式不正确。
未经授权的文件访问。
不是管理员。
您将需要收听其他Exception属性以获取更多详细信息。例如Data
将有一些信息。您可以这样做:
foreach (DictionaryEntry kvp in exception.Data)
要获取所有派生的属性(不在基Exception
类上),可以执行以下操作:
exception
.GetType()
.GetProperties()
.Where(p => p.CanRead)
.Where(p => p.GetMethod.GetBaseDefinition().DeclaringType != typeof(Exception));
IEnumerable<Exception>
而不是硬编码AggregrateException
来处理其他类似类型的属性。还要排除p.IsSpecialName
并pi.GetIndexParameters().Length != 0
避免出现问题。在输出中包括异常类型名称也是一个好主意
我做:
namespace System {
public static class ExtensionMethods {
public static string FullMessage(this Exception ex) {
if (ex is AggregateException aex) return aex.InnerExceptions.Aggregate("[ ", (total, next) => $"{total}[{next.FullMessage()}] ") + "]";
var msg = ex.Message.Replace(", see inner exception.", "").Trim();
var innerMsg = ex.InnerException?.FullMessage();
if (innerMsg is object && innerMsg!=msg) msg = $"{msg} [ {innerMsg} ]";
return msg;
}
}
}
此“漂亮打印”所有内部异常,还处理AggregateException和InnerException.Message与Message相同的情况
如果您想要有关所有异常的信息,请使用exception.ToString()
。它将从所有内部异常中收集数据。
如果只希望原始异常,请使用exception.GetBaseException().ToString()
。这将使您获得第一个异常,例如,最深层的内部异常或没有内部异常的当前异常。
例:
try {
Exception ex1 = new Exception( "Original" );
Exception ex2 = new Exception( "Second", ex1 );
Exception ex3 = new Exception( "Third", ex2 );
throw ex3;
} catch( Exception ex ) {
// ex => ex3
Exception baseEx = ex.GetBaseException(); // => ex1
}
建立在nawfal的答案上。
当使用他的答案时,缺少一个变量aggrEx,我添加了它。
文件ExceptionExtenstions.class:
// example usage:
// try{ ... } catch(Exception e) { MessageBox.Show(e.ToFormattedString()); }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YourNamespace
{
public static class ExceptionExtensions
{
public static IEnumerable<Exception> GetAllExceptions(this Exception exception)
{
yield return exception;
if (exception is AggregateException )
{
var aggrEx = exception as AggregateException;
foreach (Exception innerEx in aggrEx.InnerExceptions.SelectMany(e => e.GetAllExceptions()))
{
yield return innerEx;
}
}
else if (exception.InnerException != null)
{
foreach (Exception innerEx in exception.InnerException.GetAllExceptions())
{
yield return innerEx;
}
}
}
public static string ToFormattedString(this Exception exception)
{
IEnumerable<string> messages = exception
.GetAllExceptions()
.Where(e => !String.IsNullOrWhiteSpace(e.Message))
.Select(exceptionPart => exceptionPart.Message.Trim() + "\r\n" + (exceptionPart.StackTrace!=null? exceptionPart.StackTrace.Trim():"") );
string flattened = String.Join("\r\n\r\n", messages); // <-- the separator here
return flattened;
}
}
}
e.StackTrace == null