2010-04-13 7 views
9

мой код довольно хорошо покрыт обработкой исключений (try..except). Некоторые исключения не ожидаются, и некоторые исключения случаются довольно часто, что ожидается и будет нормально. Теперь я хочу добавить некоторые автоматические тесты для этого кода. Было бы хорошо знать, сколько исключений произошло во время выполнения, поэтому я могу позже увидеть, было ли ожидаемое число поднято или что-то неожиданное произошло. Я не хочу загромождать каждый блок обработки исключений с кодом отладки, поэтому мой вопрос:Возможно ли иметь глобальный крюк исключения?

Есть ли способ установить какой-либо глобальный обработчик исключений, который находится прямо перед всеми остальными блоками обработки исключений? Я ищу центральное место для регистрации этих исключений.

Спасибо за любые предложения!

(И если это имеет значение: это Delphi 2009)

ответ

14

Вы можете сделать следующее:

  • сохранить значение переменной System.RaiseExceptObjProc, которая в обычном приложении Delphi указывает на SysUtils.RaiseExceptObject
  • создайте свой собственный процесс «RaiseExceptObject» и назначьте его переменной RaiseExceptObjProc
  • в вашем собственном «RaiseExceptObject» «proc вы можете делать то, что хотите, а затем вызывать сохраненное значение RaiseExceptObjProc

Подробнее см. выше в описании переменных и процедур.

+0

Woohoo! Вот и все :) Большое спасибо за этот совет! И для записи: 1) Подпись 'RaiseExceptObjProc':' procedure (P: PExceptionRecord) '2) кажется, что мне не нужно вызывать старый' RaiseExceptObjProc' в моем обработчике 3) Я читаю, что это доступно, поскольку Delphi 2009 (хорошо для меня), но я не уверен в этом –

+0

Ok SysUtils.pas уже назначает 'RaiseExceptObjProc'. Может быть, это действительно должно быть вызвано моим проводником. –

+0

эй, пожалуйста, укажите пример? :) – PresleyDias

0

JCL имеет собственный диалог исключение. Просто добавьте это диалоговое окно в свой проект, он будет обрабатывать все неожиданные исключения. Подробная информация находится в этой папке JCL: jcl \ experts \ debug. Также есть текстовый файл, который шаг за шагом описывает, как его использовать.

+0

OP ищет возможность подключения к * обработанным * исключениям. –

8

Я думаю, вы можете использовать функцию API AddVectoredExceptionHandler.

Вот небольшой пример того, как использовать:

var 
    f : TFileStream; 

    function VectoredHandler(ExceptionInfo : PEXCEPTION_POINTERS): LongInt; stdcall; 
    var 
     s : String; 
    begin 
     S := Format('Exception code %x address %p'#10#13, [ExceptionInfo^.ExceptionRecord^.ExceptionCode, 
     ExceptionInfo^.ExceptionRecord^.ExceptionAddress]); 
     f.WriteBuffer(PChar(s)^, Length(s) * sizeof(wchar)); 
     FlushFileBuffers(f.Handle); 
     OutputDebugString(PChar(Format('ExceptionCode: %x', [ExceptionInfo^.ExceptionRecord^.ExceptionCode]))); 
     result := EXCEPTION_CONTINUE_SEARCH ; 
    end; 


    initialization 
     AddVectoredExceptionHandler(0, VectoredHandler); 
+0

Это исключение ловушек на уровне win32, решение Дмитрия Арефьева, но я больше ожидал. – Remko

+0

Спасибо за внимание к этим функциям, я думаю, что это может пригодиться для тех, кто делает чистую Win32. Решение Дмитрия было просто проще в моем случае. –

+0

+1 Потому что мне просто нужен этот вызов API для поддержки старой версии Delphi (например, Delphi 6-7), в которой RaiseExceptObjProc не существует. –

1

Вы можете добавить пользовательский обработчик к madExcept, который затем позволит вам получить полную трассировку стека, а также продолжить.

+0

Но * как бы вы это сделали? – Arafangion

+0

@Arafangion Я бы начал с чтения документации для madExcept, которая расскажет вам все, что вам нужно знать. По сути, вы создаете обработчик исключений (try/except), а затем передаете объект исключения в HandleException для обработки madExcept, что делает магию. – mj2008

+0

Документация неясна в отношении обработки исключений * uncaught *, хотя, особенно, когда вы начинаете заботиться о обработке исключений SEH. – Arafangion

Смежные вопросы