私の完全を示す適切な方法は何ですかInnerException
。
私の一部のInnerExceptionsには別の例外がInnerException
あり、かなり深く進んでいることがわかりました。
ウィルInnerException.ToString()
私のために仕事をするか、私はをループする必要がありますInnerExceptions
し、構築String
してStringBuilder
?
私の完全を示す適切な方法は何ですかInnerException
。
私の一部のInnerExceptionsには別の例外がInnerException
あり、かなり深く進んでいることがわかりました。
ウィルInnerException.ToString()
私のために仕事をするか、私はをループする必要がありますInnerExceptions
し、構築String
してStringBuilder
?
回答:
単純に印刷できexception.ToString()
ますInnerException
。これには、ネストされたすべてののフルテキストも含まれます。
ToString
説明されているように、内部例外のカスタムメソッドを呼び出しません。。
使うだけ 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())
}
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()
メソッドを使用してデバッグするために、スタックトレース付きのエラー全体を電子メールで開発チームに送信する1つのリスナーと、スタックトレースなしで毎日発生したすべてのエラーの履歴を含むログをファイルに書き込むリスナーを1つ用意できます。.GetFullMessage()
方法。
ex
ありAggregateException
、内部例外のどれもが、この出力に含まれません
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());
外部集計が発生しました。
インナーアグリEX。
番号の形式が正しくありません。
不正なファイルアクセス。
管理者ではありません。
詳細については、他の例外プロパティをリッスンする必要があります。たとえば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;
}
}
}
これはすべての内部例外を「きれいに出力」し、AggregateExceptionsと、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