Posted By

sholmes on 03/16/08


Tagged

exception global Handling


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

icebob


Global Exception Handling


 / Published in: Pascal
 

URL: http://www.davinciunltd.com/2007/11/crashing-like-vb/

« WordPress upgraded to 2.3.1CodeRage II is a Success »Crashing Like VB I always thought Delphi’s global exception handler was a great feature. It allows your program to continue after an otherwise unhandled exception would have caused it to terminate. Typically in a serious application you would assign your own global exception handler, or used one of the great 3rd part exception handlers like madExcept or Exceptional Magic (I love that name!) They both provide a nice dialog, stack trace, logging and reporting.

Well it turns out that if you want to be Microsoft Windows Vista Logo certified, then you need to crash your application on certain exceptions.

Applications must handle only exceptions that are known and expected, and Windows Error Reporting must not be disabled. If a fault (such as an Access Violation) is injected into an application, the application must allow Windows Error Reporting to report this crash. (from requirement 3.2 Resilient Software: Eliminate Application Failures)

Microsoft’s rational for this requirement is the ISV will receive the error report Microsoft collects for them. I guess most software developers don’t have access to tools like we do in Delphi to catch exceptions and log them for us.

So short of tossing out the Forms unit and writing everything from scratch, how can you get around the usefulness of the global exception handler.

My first thought was to create a custome application exception handler by placing a TApplicationEvents on your main form and assigning the OnException event. In the event include the line

raise e; This will pass an exception up to the operating system and terminate your application, at least when I tested it in Delphi 2007. When I tried it in Delphi 7, it didn’t work right.

A more elegant and involved solution:

  1. First you need a couple global variables:
  2.  
  3. var
  4. GlobalExcept: Exception;
  5. GlobalExceptAddr: Pointer;
  6.  
  7. And a global exception handler:
  8.  
  9. procedure TForm1.ApplicationException(Sender: TObject; E: Exception);
  10. begin
  11. if E is EAccessViolation then
  12. begin
  13. // Keep the exception object from being destroyed!
  14. AcquireExceptionObject;
  15. GlobalExcept := e;
  16. GlobalExceptAddr := ExceptAddr;
  17. Application.Terminate;
  18. end;
  19. end;
  20.  
  21. The rest of the magic happens in the project file (DPR)
  22.  
  23. begin
  24. GlobalExcept := nil;
  25. GlobalExceptAddr := nil;
  26. try
  27. Application.Initialize;
  28. Application.CreateForm(TForm1, Form1);
  29. Application.Run;
  30. finally
  31. if Assigned( GlobalExcept ) then
  32. begin
  33. raise GlobalExcept at GlobalExceptAddr;
  34. end;
  35. end;
  36. end.

Report this snippet  

You need to login to post a comment.