Кроме Proc не вызывается в Windows - PullRequest
4 голосов
/ 22 октября 2008

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

Я ожидаю, что результат будет:

Начиная
Дисплей: необработанный

но все, что он делает, это отображение:

Начиная

Затем через 5 секунд Windows возвращает командную строку.

Почему обработчик не вызывается должным образом?

P.S. Я проводил эти тесты в консольном приложении для тестирования.

EDIT:

Вот еще немного информации:

Очевидно, что когда у вас есть назначенный ExceptProc, ваша программа не должна выдавать обычную ошибку 217 во время выполнения. Я предполагаю, что это то, что ловит окна, однако из того, что я вижу, моя программа выдает эту ошибку во время выполнения, и я не могу заставить ErrorProc перехватить ее.

Ответы [ 2 ]

8 голосов
/ 22 октября 2008

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

0 голосов
/ 22 октября 2008

Интересно.

Пользовательский обработчик исключений вызывается, если вы запускаете приложение в Delphi IDE (пробовал с 2007 года), но не запускаете его из командной строки.

Еще одна интересная вещь - я изменил основной код программы на

begin
  WriteLn('Starting');
  try
    ExceptProc := @ExceptionHandler;
    Unhandled;
  finally Readln; end;
end.

и заметил, что сообщение об исключении отображается только ПОСЛЕ того, как я нажимаю клавишу Enter (чтобы получить некоторый ввод в Readln). Следовательно, ваш обработчик вызывается не тогда, когда возникает исключение, а когда он обрабатывается (в неявном try..except, который оборачивает весь ваш код). Имеет смысл.

Должно быть что-то с этой неявной попыткой ... кроме этого, но у меня нет отладчика не-Delphi на этой машине, и я не могу копать дальше. Может быть, кто-то знает ответ ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...