2008-10-22 6 views
4

J'essaie actuellement de créer un gestionnaire d'exceptions intégré à mon service Windows qui, lors d'une exception non gérée, envoie un message à un autre programme. J'ai construit la méthode et ai fait fonctionner la communication, mais il semble que chaque fois que mon programme lance l'erreur, (j'ai un appel de relance dans le code pour le forcer.) Windows l'attrape à la place et le gestionnaire n'est pas appelé. Quelqu'un peut-il expliquer ce que je fais de mal?ExceptProc n'est pas appelé dans Windows

code simplifié pour expliquer:

procedure unhandled(); 
    begin 
    raise Exception.Create('Unhandled'); 
    end; 

procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer); 
    begin 
    WriteLn('Display: ' + Exception(ExceptObject).Message); 
    //send Message Here 
    end; 

J'appelle ce code pour l'exécuter:

WriteLn('Starting');  

ExceptProc := @ExceptionHandler;  

unhandled(); 

Je pense que la sortie soit:

À partir
Affichage: Non manipulé

mais tout ce qu'il ne fait qu'afficher:

À partir

Puis fenêtres retourne une invite de commande après environ 5 secondes.

Pourquoi le gestionnaire n'est-il pas correctement appelé?

P.S. J'ai exécuté ces tests dans une application de console pour tester.

EDIT:

Voici quelques plus d'informations:

Apparemment, lorsque vous avez un ExceptProc affecté, votre programme ne devrait pas jeter l'erreur d'exécution 217 normale. Je devine que c'est ce que Windows attrape, De ce que je peux voir cependant, mon programme jette cette erreur d'exécution, et je ne peux pas obtenir un ErrorProc pour l'attraper non plus.

Répondre

8

Il vous manque un appel à SetErrorMode():

SetErrorMode(SEM_NOGPFAULTERRORBOX); 

Cela est nécessaire pour éviter que le système d'exploitation unhandled exception filter de montrer une boîte de dialogue/afficher le débogueur attach boîte de dialogue.Voici un exemple complet qui se comporte comme prévu sur ma machine:

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

Notez que l'effet de SetErrorMode() est globale dans tous les threads du processus en cours.

0

Intéressant.

Un gestionnaire d'exceptions personnalisé est appelé si vous exécutez l'application dans Delphi IDE (essayé avec 2007) mais pas si vous l'exécutez à partir de l'invite de commande.

Une autre chose intéressante - j'ai changé le code principal du programme à

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

et a remarqué que message d'exception ne s'affiche lorsque j'appuie sur la touche Entrée (pour obtenir une entrée au Readln). Par conséquent, votre gestionnaire n'est pas appelé lorsque l'exception se produit mais quand il est géré (dans try..except implicite qui enveloppe tout votre code). Donne un sens.

Doit être quelque chose avec ce try..except implicite, mais je manque d'un débogueur non-Delphi sur cette machine et ne peut pas creuser plus loin. Peut-être que quelqu'un d'autre connaît la réponse ...

Questions connexes