none
How does a C# unhandled exception expose an equivalent _EXCEPTION_POINTERS struct RRS feed

  • Question

  • Good morning, gentlemen,

    I once worked on a C++ exception filter which extracts the error code (like 0xC0000005) and the offset of the exception from a _EXCEPTION_POINTERS struct, and use these 2 values (as well as other information) to identify an application crash .

    Now there is need to use this filter to handle the crashes in the .Net/WPF application. My intrition is this idea is not practical, but I can not explain why to the boss, and...he is really keen on this thing.

    My questions:

    1. In the first place,  C# application can call SetUnhandledExceptionFilter using P/Invoke to register my exception filter, right? Even if it works, I feel this so unnatual, since C# has its own way to define such a filter (using Application.ThreadException event and AppDomain.UnhandledException event);

    2. Suppose an unhandled exception occurs,  and my exception filter is triggered.  Can I extract the values (error code/offset) from the _EXCEPTION_POINTERS struct as I could on the C++ applications? Or does an unhandled exception in C# exposes an equivalent _EXCEPTION_POINTERS struct?

    3. The most mysterious thing to me is, even if I can extract the error code/offset values, I suspect that the values can vary from run to run even if it is the same exception occurs.

    . The CLR can do optimizations at runtime which affects the offset of exception. My INTRITION I mentioned before is actually "Since the CLR has taken over the management of memory layout, the GAC and other things, we should not make assumption that the CLR preserve the exception address for you."

    . User-defined exceptions (derived from System.Exception type) may not have a corresponding error code like 0xC0000005. Or even worse, they have the same error code so the exception filter can not distinguish user-defined exceptions.

    What is your idea? And do you see other reason why this idea can not work? Or actually It can work but in a more better, elegant way?

    Thank you in advance.

     

    Friday, October 29, 2010 3:03 AM

Answers

  • >  (error code/offset)

    In the UnhandledException event, cast ExceptionObject to type Exception (if possible) and look at its StackTrace property.  If you are logging, just call ToString() instead of using StackTrace as this will include the trace as well as the full exception message.

    For details in a way that you can process programmatically, you can instead pass the Exception into the constructor of System.Diagnostics.StackTrace.  This has methods to obtain StackFrame objects.  The StackFrame object has goodies including:

    GetFileLineNumber()
    GetFileName()
    GetILOffset()
    GetMethod()

    You will be able get method names and line offsets (which may be slightly off from the actual point of the error due to inlining and other optimizations).  However, to get detailed debug information like line numbers you must deploy the .pdb file alongside the .exe.  Note that you should never deploy a Debug build in production, however there are options so that a .pdb file is generated even for a Release build.

    If you collect the offset information but do not deploy the .pdb, you could still translate the offset information "manually" if you have the pdb.  See this: http://timstall.dotnetdevelopersjournal.com/getting_file_and_line_numbers_without_deploying_the_pdb_file.htm

     

     

     

    • Marked as answer by kennyzx Saturday, October 30, 2010 11:44 AM
    Saturday, October 30, 2010 1:03 AM
  • It turns out that for .NET application crashes, Windows report 9 parameters (also known as Watson Bucket) to WinQual site in the WER report.

    And for C++ applications, Windows report 8 parameters to WinQual site in the WER report. 

    The difference is for .NET applications, the offset of a crash is represented by 2 parameters,  the first is the faulting method's index into the MethodDef table of defining assembly,  the second is the IL offset to the entry of that method.  (Sorry I am not a native English speaker, may have syntax errors in my explanations).

    For those who want to get a Watson Bucket for a .NET crash,   there are two posts that answer my questions perfectly.

    Decoding clr20r3 .NET exception – using mono cecil

    and

    Exploring UnhandledException in .NET and Watson buckets

     

     


    • Marked as answer by kennyzx Monday, April 18, 2011 9:18 AM
    • Edited by kennyzx Monday, April 18, 2011 9:30 AM explanation
    Monday, April 18, 2011 9:17 AM

All replies

  • >  (error code/offset)

    In the UnhandledException event, cast ExceptionObject to type Exception (if possible) and look at its StackTrace property.  If you are logging, just call ToString() instead of using StackTrace as this will include the trace as well as the full exception message.

    For details in a way that you can process programmatically, you can instead pass the Exception into the constructor of System.Diagnostics.StackTrace.  This has methods to obtain StackFrame objects.  The StackFrame object has goodies including:

    GetFileLineNumber()
    GetFileName()
    GetILOffset()
    GetMethod()

    You will be able get method names and line offsets (which may be slightly off from the actual point of the error due to inlining and other optimizations).  However, to get detailed debug information like line numbers you must deploy the .pdb file alongside the .exe.  Note that you should never deploy a Debug build in production, however there are options so that a .pdb file is generated even for a Release build.

    If you collect the offset information but do not deploy the .pdb, you could still translate the offset information "manually" if you have the pdb.  See this: http://timstall.dotnetdevelopersjournal.com/getting_file_and_line_numbers_without_deploying_the_pdb_file.htm

     

     

     

    • Marked as answer by kennyzx Saturday, October 30, 2010 11:44 AM
    Saturday, October 30, 2010 1:03 AM
  • It turns out that for .NET application crashes, Windows report 9 parameters (also known as Watson Bucket) to WinQual site in the WER report.

    And for C++ applications, Windows report 8 parameters to WinQual site in the WER report. 

    The difference is for .NET applications, the offset of a crash is represented by 2 parameters,  the first is the faulting method's index into the MethodDef table of defining assembly,  the second is the IL offset to the entry of that method.  (Sorry I am not a native English speaker, may have syntax errors in my explanations).

    For those who want to get a Watson Bucket for a .NET crash,   there are two posts that answer my questions perfectly.

    Decoding clr20r3 .NET exception – using mono cecil

    and

    Exploring UnhandledException in .NET and Watson buckets

     

     


    • Marked as answer by kennyzx Monday, April 18, 2011 9:18 AM
    • Edited by kennyzx Monday, April 18, 2011 9:30 AM explanation
    Monday, April 18, 2011 9:17 AM