В настоящее время я пытаюсь создать обработчик исключений, встроенный в мою службу Windows, который при необработанном исключении отправляет сообщение в другую программу. Я создал метод и получил связь, но кажется, что каждый раз, когда моя программа выдает ошибку (у меня есть вызов повышения в коде для ее принудительного выполнения), окна улавливают ее, а обработчик не вызывается. Может кто-нибудь объяснить, что я делаю не так ?.
Упрощенный код для объяснения:
procedure unhandled();
begin
raise Exception.Create('Unhandled');
end;
procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
WriteLn('Display: ' + Exception(ExceptObject).Message);
//send Message Here
end;
Я вызываю этот код, чтобы запустить его:
WriteLn('Starting');
ExceptProc := @ExceptionHandler;
unhandled();
Я ожидал, что результат будет:
Starting
Display: Unhandled
но все, что он делает, это отображает:
Starting
Затем Windows возвращает командную строку примерно через 5 секунд.
Почему обработчик не вызывается должным образом?
P.S. Я проводил эти тесты в консольном приложении для тестирования.
Обновлено:
Вот еще немного информации:
По-видимому, когда у вас есть назначенный ExceptProc, ваша программа не должна выдавать обычную ошибку времени выполнения 217. Я предполагаю, что это то, что улавливают окна. Однако из того, что я вижу, моя программа выдает эту ошибку времени выполнения, и я не могу получить ErrorProc, чтобы ее поймать.





Интересно.
Пользовательский обработчик исключений вызывается, если вы запускаете приложение в IDE Delphi (пытались с 2007), но не, если вы запускаете его из командной строки.
Еще один интересный момент - я изменил основной программный код на
begin
WriteLn('Starting');
try
ExceptProc := @ExceptionHandler;
Unhandled;
finally Readln; end;
end.
и заметил, что сообщение об исключении отображается только ПОСЛЕ того, как я нажимаю клавишу Enter (чтобы ввести некоторые данные в Readln). Следовательно, ваш обработчик вызывается не при возникновении исключения, а при его обработке (в неявном try..except, который охватывает весь ваш код). Имеет смысл.
Должно быть что-то с этой неявной попыткой ... кроме этого, но у меня на этой машине нет отладчика, отличного от Delphi, и я не могу копать дальше. Может кто-нибудь знает ответ ...
Вам не хватает вызова SetErrorMode ():
SetErrorMode(SEM_NOGPFAULTERRORBOX);
Это необходимо для предотвращения отображения диалогового окна / отображения диалогового окна подключения отладчика операционной системой фильтр необработанных исключений. Вот полный пример, который на моей машине ведет себя так, как ожидалось:
{$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.
Обратите внимание, что эффект SetErrorMode () является глобальным для всех потоков в запущенном процессе.