Alle CLR-Ausnahmen (die ersten und diejenigen, die möglicherweise zu einem Abbruch der Anwendung führen) werden vom CLR-Laufzeitanbieter bei Aktivierung in ETW protokolliert.
Dies ist ein vollständig "strukturiertes" Ereignis MIT Callstacks (wenn Sie sie wollen). In der Tat können Sie eine Überwachungsanwendung mit dem Traceevent NuGet Paket schreiben (Install-Package Microsoft.Diagnostics.Tracing.TraceEvent)
Ich bin Einfügen Überwachung Code, den ich oft verwenden. Fügen Sie dies in eine Konsolenanwendung ein, rufen Sie die Run-Methode auf und werfen Sie einige verwaltete Ausnahmen von jedem Prozess ab. Dadurch werden die Informationen und ihre Callstacks gedruckt.
HINWEIS: Sie benötigen das referenzierte NuGet-Paket, und verweisen Sie dann auf seine Assemblys, und dann wird dieser Code kompiliert.
class TraceLogMonitor
{
static TextWriter Out = AllSamples.Out;
public static void Run()
{
var monitoringTimeSec = 10;
TraceEventSession session = null;
Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) =>
{
if (session != null)
session.Dispose();
cancelArgs.Cancel = true;
};
var exceptionGeneationTask = Task.Factory.StartNew(delegate
{
Thread.Sleep(3000);
ThrowException();
});
Timer timer = null;
using (session = new TraceEventSession("TraceLogSession"))
{
Out.WriteLine("Enabling Image load, Process and Thread events. These are needed to look up native method names.");
session.EnableKernelProvider(
KernelTraceEventParser.Keywords.ImageLoad |
KernelTraceEventParser.Keywords.Process,
KernelTraceEventParser.Keywords.None
);
Out.WriteLine("Enabling CLR Exception and Load events (and stack for those events)");
session.EnableProvider(
ClrTraceEventParser.ProviderGuid,
TraceEventLevel.Informational,
(ulong)(ClrTraceEventParser.Keywords.Jit |
ClrTraceEventParser.Keywords.JittedMethodILToNativeMap |
ClrTraceEventParser.Keywords.Loader |
ClrTraceEventParser.Keywords.Exception |
ClrTraceEventParser.Keywords.Stack));
Out.WriteLine("Enabling CLR Events to 'catch up' on JIT compiled code in running processes.");
session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Informational,
(ulong)(ClrTraceEventParser.Keywords.Jit |
ClrTraceEventParser.Keywords.JittedMethodILToNativeMap |
ClrTraceEventParser.Keywords.Loader |
ClrTraceEventParser.Keywords.StartEnumeration));
TextWriter SymbolLookupMessages = new StringWriter();
var symbolPath = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath);
SymbolReader symbolReader = new SymbolReader(SymbolLookupMessages, symbolPath.ToString());
Out.WriteLine("Open a real time TraceLog session (which understands how to decode stacks).");
using (TraceLogEventSource traceLogSource = TraceLog.CreateFromTraceEventSession(session))
{
Action<TraceEvent> PrintEvent = ((TraceEvent data) => Print(data, symbolReader));
traceLogSource.Clr.ExceptionStart += PrintEvent;
traceLogSource.Clr.LoaderModuleLoad += PrintEvent;
traceLogSource.Kernel.PerfInfoSample += ((SampledProfileTraceData data) => Print(data, symbolReader));
Out.WriteLine("Waiting {0} sec for Events. Run managed code to see data. ", monitoringTimeSec);
Out.WriteLine("Keep in mind there is a several second buffering delay");
timer = new Timer(delegate(object state)
{
Out.WriteLine("Stopped Monitoring after {0} sec", monitoringTimeSec);
if (session != null)
session.Dispose();
session = null;
}, null, monitoringTimeSec * 1000, Timeout.Infinite);
traceLogSource.Process();
}
}
Out.WriteLine("Finished");
if (timer != null)
timer.Dispose();
}
static void Print(TraceEvent data, SymbolReader symbolReader)
{
if (data.Opcode == TraceEventOpcode.DataCollectionStart)
return;
if (data is ExceptionTraceData && ((ExceptionTraceData) data).ExceptionType.Length == 0)
return;
Out.WriteLine("EVENT: {0}", data.ToString());
var callStack = data.CallStack();
if (callStack != null)
{
ResolveNativeCode(callStack, symbolReader);
Out.WriteLine("CALLSTACK: {0}", callStack.ToString());
}
}
static private void ResolveNativeCode(TraceCallStack callStack, SymbolReader symbolReader)
{
while (callStack != null)
{
var codeAddress = callStack.CodeAddress;
if (codeAddress.Method == null)
{
var moduleFile = codeAddress.ModuleFile;
if (moduleFile == null)
Trace.WriteLine(string.Format("Could not find module for Address 0x{0:x}", codeAddress.Address));
else
codeAddress.CodeAddresses.LookupSymbolsForModule(symbolReader, moduleFile);
}
callStack = callStack.Caller;
}
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private static void ThrowException()
{
ThrowException1();
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private static void ThrowException1()
{
Out.WriteLine("Causing an exception to happen so a CLR Exception Start event will be generated.");
try
{
throw new Exception("This is a test exception thrown to generate a CLR event");
}
catch (Exception) { }
}
}
Da kann man nicht stark Ausnahmen gegen den Eventsource-Typ verwenden würde ich am besten, es einfach sein Aufruf wie folgt: EventSource.Log.Failure (MyException.ToString())? – jaffa
das wäre ok. – magicandre1981