2

My situation is as follows:

  • I have a form FormBase
  • From this FormBaseList and FormBaseDetail are inherited

now on my mainform I want to log some exceptions from then FirstChanceException event. I log the Exception.Message and the full stacktrace

But in the stacktrace I have a problem.
For example I create a form FormCustomerDetail and its derived from FormBaseDetail.
And an exception occurs in a protected or private method defined in FormBaseDetail then the stacktrace will show FormBaseDetail in stead of FormCustomerDetail
This is a problem for me, because now I cant know what actual form the exception happend on. There are about 50 forms derived from FormBaseDetail

So the question is, is there a way in the FirstChanceException event to retrieve the classname of the actual form ? Or the Name ?

AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;

private void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
    StackTrace stackTraceObject = new StackTrace();
    string stackTrace = stackTraceObject.ToString();

    // I need to retrieve the actual form name or classname here...
    LogError(
      //ActualFormName + Environment.NewLine +  
      e.Exception.GetType().FullName + Environment.NewLine +  
      e.Exception.Message + Environment.NewLine + 
      stackTrace);
}

Example of a logentry:

System.FormatException
Cannot convert xx to type boolean...
...
at Test_app.FormBaseDetail.OpenTables()  
at Test_app.FormBaseDetail.PrepareFormLoad()
...

What I would like to get

Exeption occured in FormCustomerDetail
System.FormatException
Cannot convert xx to type boolean...
...
at Test_app.FormBaseDetail.OpenTables()  
at Test_app.FormBaseDetail.PrepareFormLoad()
...
GuidoG
  • 11,359
  • 6
  • 44
  • 79
  • You're looking for a way to resolve the instances of local variables on stack when an exception occurs. Unfortunately the `StackTrace` class does not appear to support this. The debugger does, but that's probably not helpful here. -- Incidentally, it's first _chance_, not first change. – 500 - Internal Server Error Dec 13 '18 at 11:21

1 Answers1

1

Naive way would be to actually log it inside the base form - i.e. have something like:

class FormBaseDetail 
{
   private void Guard(Action a)
   {
       try { a.Invoke(); }
       catch(Exception e)
       {
          throw new Exception("Exception on '" + this.GetType() + "'", e);
       }
   }

   // pretty much everywhere in base class
   public void PrepareFormLoad() 
   {
      Guard(() => { ... });
   }
}

Additionally I can imagine hooking on FormLoad and putting the active type of Form into some static variable for example.

Ondrej Svejdar
  • 21,349
  • 5
  • 54
  • 89
  • yes but that will only work if i put that in every mehod of every form, right ? – GuidoG Dec 13 '18 at 11:36
  • @GuidoG - just the base form (FormBaseDetail - if exception happens in child form method (say FormCustomerDetail) you should be able to infer the type from the stack trace. But yeah - you'd have to put it into all FormBaseDetail methods. – Ondrej Svejdar Dec 13 '18 at 11:38
  • ok, but will the invoke have any effect on performance or message queu ? – GuidoG Dec 13 '18 at 11:39
  • There is very, very, small performance penalty for every try block; but on UI operation I wouldn't mind it. Ref https://stackoverflow.com/questions/1308432/do-try-catch-blocks-hurt-performance-when-exceptions-are-not-thrown – Ondrej Svejdar Dec 13 '18 at 11:40
  • Well i suppose I can give this a try – GuidoG Dec 13 '18 at 11:40