完全なInnerException
を表示する適切な方法は何ですか。
私のInnerExceptionsには別のInnerException
があり、それがかなり深く進んでいることがわかりました。
InnerException.ToString()
は私のために仕事をしますか、それともInnerExceptions
をループしてString
をStringBuilder
で構築する必要がありますか?
単純にexception.ToString()
を印刷できます。これには、ネストされたすべてのInnerException
sの全文も含まれます。
exception.ToString()
を使用するだけです
http://msdn.Microsoft.com/en-us/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())
}
@Jonの答えは、完全な詳細(すべてのメッセージとスタックトレース)と推奨されるものが必要な場合に最適なソリューションです。
ただし、内部メッセージだけが必要な場合があります。これらの場合、次の拡張メソッドを使用します。
public static class ExceptionExtensions
{
public static string GetFullMessage(this Exception ex)
{
return ex.InnerException == null
? ex.Message
: ex.Message + " --> " + ex.InnerException.GetFullMessage();
}
}
トレースとロギングに異なるリスナーがあり、それらに異なるビューが必要な場合に、このメソッドをよく使用します。その方法で、.ToString()
メソッドを使用してデバッグするために開発チームにスタックトレースでエラー全体を送信する1つのリスナーと、毎日発生したすべてのエラーの履歴をファイルに記録するリスナーを作成できます。 .GetFullMessage()
メソッドを使用したスタックトレースなし。
深い例外のMessage
s部分のみをきれいに出力するには、次のようにします。
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 exが発生しました。
内部攻撃.
番号の形式が正しくありません。
不正なファイルアクセス。
管理者ではありません。
詳細については、他のExceptionプロパティをリッスンする必要があります。例えばData
にはいくつかの情報があります。あなたができる:
foreach (DictionaryEntry kvp in exception.Data)
すべての派生プロパティ(ベースException
クラスではない)を取得するには、次のようにします。
exception
.GetType()
.GetProperties()
.Where(p => p.CanRead)
.Where(p => p.GetMethod.GetBaseDefinition().DeclaringType != typeof(Exception));
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;
}
}
}
すべての例外に関する情報が必要な場合は、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
}