ExceptProc não sendo chamado no Windows
-
03-07-2019 - |
Pergunta
Atualmente, estou tentando criar um manipulador de exceção embutido no meu serviço janelas que, em uma exceção não tratada, envia uma mensagem para outro programa. Eu construí o método e obteve o trabalho de comunicação, mas parece que cada vez que meu programa gera o erro, (eu tenho uma chamada de raise no código para forçá-lo.) Janelas capturas, em vez disso eo manipulador não é chamado. Alguém pode explicar o que estou fazendo de errado?.
código simplificado para explicar:
procedure unhandled();
begin
raise Exception.Create('Unhandled');
end;
procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
WriteLn('Display: ' + Exception(ExceptObject).Message);
//send Message Here
end;
Eu chamo este código para executá-lo:
WriteLn('Starting');
ExceptProc := @ExceptionHandler;
unhandled();
Eu esperaria que a saída seja:
Iniciando
Display: Unhandled
mas tudo que faz é display:
Iniciar
Em seguida, o Windows retorna um prompt de comando após cerca de 5 segundos.
Por que não é o manipulador a ser devidamente chamado?
P.S. Fui correndo esses testes em um console app para testar.
EDIT:
Aqui está mais algumas informações:
Aparentemente, quando você tem um ExceptProc atribuído, o seu programa não deve jogar o erro normal de tempo de execução 217. Eu estou supondo que este é o que o Windows está pegando, Pelo que posso ver, no entanto, o meu programa está jogando esse erro de tempo de execução, e eu não posso ter uma ErrorProc para pegá-lo também.
Solução
Está faltando uma chamada para SetErrorMode () :
SetErrorMode(SEM_NOGPFAULTERRORBOX);
Isso é necessário para evitar que o OS filtro de exceção não tratada de mostrar uma caixa de diálogo / exibindo o depurador caixa de diálogo anexar. Aqui está um exemplo completo que se comporta como esperado na minha máquina:
{$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 que o efeito da SetErrorMode () é global em todos os segmentos no processo de execução.
Outras dicas
Interessante.
manipulador de exceção personalizada é chamado, se você executar o aplicativo em Delphi IDE (tentou a 2007), mas não se você executá-lo a partir do prompt de comando.
Outra coisa interessante - eu mudei o código do programa principal para
begin
WriteLn('Starting');
try
ExceptProc := @ExceptionHandler;
Unhandled;
finally Readln; end;
end.
e notou que mensagem de exceção é exibido apenas depois de premir a tecla Enter (para obter alguma entrada para o readln). Portanto, o manipulador não é chamado quando exceção ocorre, mas quando ele é tratado (em try..except implícita que envolve todo o seu código). Faz sentido.
Deve ser algo com este try..except implícita então, mas me falta um depurador não-Delphi nesta máquina e não pode cavar ainda mais. Talvez alguém sabe a resposta ...