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.

Foi útil?

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 ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top