I am currently trying to create an Exception handler built into my windows service that, on an unhandled exception, sends a message to another program. I have built the method and gotten the communication working, but it seems that every time my program throws the error, (I have a raise call in the code to force it.) windows catches it instead and the Handler isn't called. Can anyone explain what I am doing wrong?.
Simplified Code to explain:
procedure unhandled();
begin
raise Exception.Create('Unhandled');
end;
procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
WriteLn('Display: ' + Exception(ExceptObject).Message);
//send Message Here
end;
I call this code to run it:
WriteLn('Starting');
ExceptProc := @ExceptionHandler;
unhandled();
I would expect the output to be:
Starting
Display: Unhandled
but all it does is display:
Starting
Then windows returns a command prompt after about 5 seconds.
Why isn't the handler being properly called?
P.S. I've been running these tests in a console app for testing.
EDIT:
Here's some more information:
Apparently when you have an assigned ExceptProc, your program shouldn't throw the normal runtime 217 error. I'm guessing this is what windows is catching, From what I can see however, my program is throwing that runtime error, and I can't get an ErrorProc to catch it either.
You are missing a call to SetErrorMode():
SetErrorMode(SEM_NOGPFAULTERRORBOX);
This is needed to prevent the OS unhandled exception filter from showing a dialog box / displaying the debugger attach dialog box. Here's a complete sample that behaves as expected on my machine:
{$apptype console}
uses Windows, SysUtils;
procedure unhandled();
begin
raise Exception.Create('Unhandled');
end;
procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
Writeln('here');
WriteLn('Display: ' + Exception(ExceptObject).Message);
Flush(Output);
Halt(1);
end;
procedure Go;
begin
unhandled;
end;
begin
ExceptProc := @ExceptionHandler;
SetErrorMode(SEM_NOGPFAULTERRORBOX);
Go;
end.
Note that the effect of SetErrorMode() is global across all threads in the running process.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With