ExceptProc не вызывается в Windows

В настоящее время я пытаюсь создать обработчик исключений, встроенный в мою службу 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, чтобы ее поймать.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
752
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Интересно.

Пользовательский обработчик исключений вызывается, если вы запускаете приложение в 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 () является глобальным для всех потоков в запущенном процессе.

Другие вопросы по теме