4

ロギングにNLogを使用しています。System.Diagnostics.Trace()に出力する方法を設定しようとしているので、次のようにNLog.configファイルを設定します。

<targets>
  <target name="debugOutput" xsi:type="Trace" />
</targets>
<rules>
  <logger name="*" minlevel="Debug" writeTo="debugOutput" />
</rules>

これは、Error()とFatal()を除くすべてのログレベルで正常に機能します。

たとえば、次のコードです。

private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
...
_logger.Trace("Sample trace message\n");
_logger.Debug("Sample debug message\n");
_logger.Info("Sample informational message\n");
_logger.Warn("Sample warning message\n");
_logger.Error("Sample error message\n");
_logger.Fatal("Sample fatal error message\n");

_logger.Error()および_logger.Fatal()が呼び出されると、例外がスローされます。

2012-09-28 12:08:04.9296|DEBUG|ClassLibraryUsingNLog.Test|Sample debug message

2012-09-28 12:08:04.9636|INFO|ClassLibraryUsingNLog.Test|Sample informational message

2012-09-28 12:08:04.9906|WARN|ClassLibraryUsingNLog.Test|Sample warning message

---- DEBUG ASSERTION FAILED ----
---- Assert Short Message ----
2012-09-28 12:08:05.0176|ERROR|ClassLibraryUsingNLog.Test|Sample error message

---- Assert Long Message ----

   at NLog.Targets.TraceTarget.Write(LogEventInfo logEvent)
   at NLog.Targets.Target.Write(AsyncLogEventInfo logEvent)
   at NLog.Targets.Target.WriteAsyncLogEvent(AsyncLogEventInfo logEvent)
   at NLog.LoggerImpl.WriteToTargetWithFilterChain(TargetWithFilterChain targetListHead, LogEventInfo logEvent, AsyncContinuation onException)
   at NLog.LoggerImpl.Write(Type loggerType, TargetWithFilterChain targets, LogEventInfo logEvent, LogFactory factory)
   at NLog.Logger.WriteToTargets[T](LogLevel level, IFormatProvider formatProvider, T value)
   at NLog.Logger.Error(String message)
   at ClassLibraryUsingNLog.Test.Func() in c:\Test\CS4.x\ClassLibraryUsingNLog\Test.cs:line 15
   at ConsoleAppIndirectlyUsesNLog.Program.Main(String[] args) in C:\Test\CS4.x\ConsoleAppIndirectlyUsesNLog\Program.cs:line 11

First-chance exception at 0x7686b9bc in ConsoleAppIndirectlyUsesNLog.exe: Microsoft C++ exception: EEMessageException at memory location 0x0053e8d4..
---- DEBUG ASSERTION FAILED ----
---- Assert Short Message ----
2012-09-28 12:08:06.7936|FATAL|ClassLibraryUsingNLog.Test|Sample fatal error message

---- Assert Long Message ----

   at NLog.Targets.TraceTarget.Write(LogEventInfo logEvent)
   at NLog.Targets.Target.Write(AsyncLogEventInfo logEvent)
   at NLog.Targets.Target.WriteAsyncLogEvent(AsyncLogEventInfo logEvent)
   at NLog.LoggerImpl.WriteToTargetWithFilterChain(TargetWithFilterChain targetListHead, LogEventInfo logEvent, AsyncContinuation onException)
   at NLog.LoggerImpl.Write(Type loggerType, TargetWithFilterChain targets, LogEventInfo logEvent, LogFactory factory)
   at NLog.Logger.WriteToTargets[T](LogLevel level, IFormatProvider formatProvider, T value)
   at NLog.Logger.Fatal(String message)
   at ClassLibraryUsingNLog.Test.Func() in c:\Test\CS4.x\ClassLibraryUsingNLog\Test.cs:line 16
   at ConsoleAppIndirectlyUsesNLog.Program.Main(String[] args) in C:\Test\CS4.x\ConsoleAppIndirectlyUsesNLog\Program.cs:line 11

ただし、次のようにxsi:typeを "OutputDebugString"に変更して、代わりにOutputDebugStringに出力するように構成ファイルを変更した場合:

<targets>
  <target name="debugOutput" xsi:type="OutputDebugString" />
</targets>
<rules>
  <logger name="*" minlevel="Debug" writeTo="debugOutput" />
</rules>

その後、例外なくすべて期待どおりに機能します。この出力は、デバッグ出力ウィンドウに表示されます(アンマネージデバッグをサポートするようにプロジェクト設定を変更した後)。

2012-09-28 12:16:13.4166|DEBUG|ClassLibraryUsingNLog.Test|Sample debug message
2012-09-28 12:16:13.4166|INFO|ClassLibraryUsingNLog.Test|Sample informational message
2012-09-28 12:16:13.4166|WARN|ClassLibraryUsingNLog.Test|Sample warning message
2012-09-28 12:16:13.4266|ERROR|ClassLibraryUsingNLog.Test|Sample error message
2012-09-28 12:16:13.4266|FATAL|ClassLibraryUsingNLog.Test|Sample fatal error message

Logger.Error()とLogger.Fatal()の例外をスローせずに、System.Diagnostics.Trace()に出力してこれを機能させる方法はありますか?そして、なぜそれはこのように動作するのですか?

4

3 に答える 3

4

最初の答えに加えて:

NLog TraceTarget は、LogLevel が >= LogLevel.Error のときに Trace.Fail を呼び出します。

Trace.Fail メソッドはここに文書化されていますhttp://msdn.microsoft.com/en-us/library/95s7fba5.aspx

問題の原因は次のようです。

既定のトレース リスナーの既定の動作では、アプリケーションがユーザー インターフェイス モードで実行されている場合はメッセージ パラメーターがメッセージ ボックスに出力され、Listeners コレクションの TraceListener インスタンスに出力されます。

コンソール アプリで問題を示すことができます

 static void Main( string[ ] args ){
  Trace.TraceInformation( "Hello world" );
  Trace.Fail("A failure");
}

独自の TraceListener を追加する前に DefaultTraceListener を削除することで、これを「修正」できます。

static void Main( string[ ] args ){
  Trace.Listeners.Clear();
  Trace.Listeners.Add( new ConsoleTraceListener( ) );
  Trace.TraceInformation( "Hello world" );
  Trace.Fail("A failure");
}

または、DefaultTraceListener の AssertUiEnabled プロパティを false に設定することもできます。

static void Main( string[ ] args ){
  Trace.Listeners.OfType<DefaultTraceListener>().First().AssertUiEnabled = false;
  Trace.TraceInformation( "Hello world" );
  Trace.Fail("A failure");
}

これにより、Assert Failure ダイアログが抑制されますが、トレース出力にはまだ偽のスタック ダンプが含まれています。

ログ情報を Visual Studio の [出力] ウィンドウに送信するだけの場合は、DebuggerTarget を使用します。

于 2012-12-19T03:23:01.507 に答える
2

内部的に、TraceTarget はSystem.Diagnostics.Trace.Failを使用してメッセージを書き込みます。

NLog TraceTarget の Write メソッドのコードは次のとおりです。

protected override void Write(LogEventInfo logEvent)
{
    if (logEvent.Level >= LogLevel.Error)
    {
        Trace.Fail(this.Layout.Render(logEvent));
    }
    else
    {
        Trace.WriteLine(this.Layout.Render(logEvent));
    }
}

Trace.Fail が明らかに失敗している理由についての答えはありません。ただし、NLog が Trace.Fail を使用することを知っていれば、(NLog でログを記録しているのと同じ呼び出しサイトで) Trace.Fail を使用して実験し、Trace.Fail で何が問題になっているのかを診断できるかどうかを確認できます。app.config ファイルの System.Diagnostics 構成 (または構成の欠如) と関係がある可能性があります。

Trace.Fail の MSDN ドキュメントでは、DefaultTraceListener が存在しない場合は MessageBox が使用されると記載されていることに注意してください。出力で、コンソール アプリを使用していることに気付きました。コンソール アプリのコンテキストで MessageBox が正しく機能しない可能性はありますか?

これは、Scott Hanselman による比較的古いブログ投稿へのリンクで、問題を明らかにする可能性があります。下部に向かって、彼は非 UI コンテキストでの Trace.Fail の問題を説明し、あなたにとって有効な解決策を提案します。

要約すると、彼はこれ (具体的にはassertuienabledフラグ) を app.config/web.config に入れる (またはコードで設定する) ことを提案しています。

<configuration>
   <system.diagnostics>
      <assert assertuienabled="false" logfilename="c:\log.txt"/>
   </system.diagnostics>
</configuration>

幸運を!

于 2012-09-28T14:30:24.117 に答える