IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants VCL Delphi Discussion :

TApplicationEvents OnException Exception non attrapée


Sujet :

Composants VCL Delphi

  1. #1
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 115
    Par défaut TApplicationEvents OnException Exception non attrapée
    Dans mon programme, je lève des exceptions pour des cas particuliers tels que les requêtes, du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    raise Exception.Create('Waouu, une exception est levée!');
    Puis je récupère celle-ci dans un TApplicationEvents, dans le OnException.
    J'affiche cette expression puis je ferme le programme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
    begin
      //Affichage de l'exeption
      Application.ShowException(E);
      //Je ferme le programe
      Application.Terminate;
    end;
    Jusque la tout vas bien, sauf que...
    J'utilise une douchette donc un composant TComPort
    Dans le OnRxChar de ce composant je me retrouve à lever une exception, du meme style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    raise Exception.Create('test');
    //Lignes suivantes
    //...
    Or voila le TApplicationEvents n'attrape pas cette exception et de plus le programme n'effectue pas les lignes suivantes.
    Quel est le souci avec ce composant TComPort ? Ou du moins avec le OnRxChar ?
    Si quelqu'un pouvait m'éclairer...

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    tu n'aurais pas un try except ?
    Sinon OnException c'est la solution de dernière chance, il faut encadrer son code de try except et gérer l'exception dedans ...
    Terminer l'application dès qu'il y a une exception, c'est une drôle d'idée ?

    le OnRxChar ne serait-il pas protégé contre les excecptions justement, on peut penser que le développeur du TComPort ne souhaitait pas subir les exceptions provoqué par un Gestionnaire d'Evènement !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 115
    Par défaut
    En faite ce programme est destiné à la production (avec BDD).
    Il doit donc être très fiable et ne pas lancer de routine inutile.
    Lorsqu'il y a un quelconque problème dans le résultat d'une requête, je créer une exception. Je récupère celle-ci dans le OnException, je l'affiche puis je ferme mon logiciel pour éviter tout problème.

    Tu penses que ce principe n'est pas terrible?

    Âpres, je trouve ta supposition intéressante au sujet du TComPort. Je suis en train de regarder de plus prêt le code de ce composant.

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    Pour la Fermeture, j'ai aussi fait des programmes qui devaient tourner 24/24 lié à des Trieuses industrielles, et jamais j'ai laissé une exception de propager, tout mon code était encadré de try except, chaque exception était capturée et des procédures de correction étaient lancé
    comme un arrêt d'urgence de la trieuse, le programme de tri était sans IHM au moindre soucis l'application d'admin affichait un gros écran rouge, et si possible un Speudo-RollBack sur la Base de Données

    L'avantage du Try Except, c'est que tu sais où tu es, donc tu peux mieux tracer et donc mieux débugger, pour corriger le code (comme détecter le contexte d'Exception pour empêcher d'appeler la procédure en erreur, au lieu de laisser l'exception se déclencher surtout si c'est lié à la mémoire ou à la BDD)

    Utiliser OnException est pratique pour empêcher d'avoir des Message à l'écran, mais ce n'est pas la bonne solution pour la robutesse car tu ne sais pas quel code a déclenché l'exception, déjà séparé IHM et Traitement par des Thread, et donc gérer la mémoire proprement c'est déjà un 1er pas vers la robutesse, le mieux étant d'avoir un Service qui fait les traitements (communique avec les automates ou les logiciels annexes, pour mon cas des AS400, le truc ultra lent si l'archi n'est pas la bonne, et c'était notre cas),
    Ensuite, l'Affichage n'étant qu'une application cliente du Service.
    Ainsi tu peux planter l'IHM sans planter le traitement ...

    Les programmeurs de l'automate avaient poussé le vice encore plus loin avec une application RTX Venturcom (un sous OS qui remplace le DOS) ainsi le Window NT4 pouvait afficher un Ecran Bleu (donc plus d'admin), le programme de tri (qui communiquait nos ordres au terrain de bus de la trieuse) continuait à tourner, cela implique d'utiliser que les API Venturcom (Thread, TCP\IP, Fichier, en gros programmer sur un autre OS)


    En général, je n'avais pas d'exception, j'avais un écran bleu sous Win2K lorsque le BDE plantait après 72h (ouais je sais, j'ai utilisé Paradox, je n'ai eu qu'un mois pour ré-écrire une appli Windev, le patron voulait qu'on utilise ce langage pour notre projet, ce n'était pas crédible ! La Ré-écriture s'est faite en urgence même si j'avais vu le coup venir !)
    Du coup, j'avais inclu, un reboot du PC à 6h du matin si aucun tri n'était en cours ...
    J'avais fait une version sans BDE, plus robuste, je n'ai jamais pu la tester, je l'avais fait juste pour le fun, avec ma propre BD (Tout en RAM en fait, avec un thread s'occupant de dumper les modifs dans des fichiers)

    A l'époque, je n'utilisais pas d'objet, tout en procédural et record
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 115
    Par défaut
    Merci pour toutes ses explications.
    Je suis en train de ré-assembler mes exceptions de façon plus local.

    Ceci dit après, j'ai toujours le même problème avec mon composant TComPort
    Si j'écris ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
    begin
      showmessage('avant exception');
      raise Exception.Create('exception');
      showmessage('apres exception');
    end;
    Le programme M'affiche 'avant exception'.
    C'est tout...
    Qu'est ce que je peux faire pour remédier à ca?
    Modifier le composant ?

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    Ben ça c'est normal, l'Exception est capturé par ComPort.OnRxChar pour qu'il puisse continuer son travail
    Tu peux gérer l'exception localement par un Try Except, tu peux socker si besoin l'exception (attention, pas l'exception elle-même, le gestionnaire des exceptions ne le permet pas mais tu peux stocker message et classe)

    Voir aussi l'évènement OnError

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
    begin
      try
        showmessage('avant exception');
        raise Exception.Create('exception');
      except
        on E: Exception do
        begin
          showmessage('durant exception');
          Self.LastErrorType := ExceptClass(E.ClassType); 
          Self.LastErrorMessage := E.Message;
          // raise; // relance l'exception
        end;
      end;
     
      showmessage('apres exception');      
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 115
    Par défaut
    Ok,
    merci encore ShaiLeTroll

    Je vais suivre ta proposition sur le faite de stocker les données de l'erreur

  8. #8
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 115
    Par défaut
    Mais quand même, je ne suis pas 100% satisfait.

    Le programme qui est en cours de réalisation est une charte graphique fonctionnant avec un écran tactile. Je dois m’occuper de reprendre le code de quelqu’un afin d’y faire quelques modifications. Ce code est assez copieux (milliers de lignes). De plus il utilise une multitude de librairies. Je ne peux donc pas me permettre de rajouter des « try except » partout dans le code.
    Or j’ai besoin de crée des exceptions à certains endroits (afin de les logger dans un system de gestion d’erreur). Et je ne veux pas non plus que des messages DLG (issue d’exception que je n’ai pas géré) sorte directement sur l’écran. J’ai besoin de formater ces messages pour afficher un message précis à l’utilisateur de ce tactile.
    Existe-il une façon de récupéré toutes mes exceptions sans passer par le composant « TApplication » et son événement « OnException » ?

  9. #9
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 115
    Par défaut
    Je pense gérer les exceptions de cette façon, qu'en pensez-vous?
    Est ce que j'ai bien tout compris?

    //Déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    type
      ExceptionGrave = class(Exception)
        constructor Create(const EMessage : string; EError : integer);
      private
          FErrorCode : integer;
      public
        property ErrorCode : integer read FErrorCode write FErrorCode;
      end;
    //Implementation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    //****************************************************************************//
    //                         A la création de la form                           //
    //****************************************************************************//
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      ComPort1.Port := 'COM10';
      ComPort1.Connected := true;
    end;
     
    //Constructeur du type ExceptionGrave
    constructor ExceptionGrave.Create(const EMessage: string; EError: integer);
    begin
      Inherited Create(EMessage);
      ErrorCode := EError;
    end;
     
    //****************************************************************************//
    //                        Boutons création d'exception                        //
    //****************************************************************************//
    procedure TForm1.ButtonCreationException1Click(Sender: TObject);
    begin
      try
        raise ExceptionGrave.Create('Exception grave prévue',31);
      except
        on E: exception do
          GestionException(E);
      end;
    end;
     
    procedure TForm1.ButtonCreationException2Click(Sender: TObject);
    begin
      raise Exception.Create('Exception imprévue');
    end;
     
    //****************************************************************************//
    //                                TApllication                                //
    //****************************************************************************//
    procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
    begin
      ShowMessage('Exception attrape');
      GestionException(E);
    end;
     
    //****************************************************************************//
      //                                DOUCHETTE                                 //
    //****************************************************************************//
    procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
    begin
      try
        ShowMessage('Début de la reception de la douchette');
        raise Exception.Create('Exception dans la reception');
      except
        on E: exception do
          GestionException(E);
      end;
    end;
     
    //****************************************************************************//
    //                          Gestionnaire d'exception                          //
    //****************************************************************************//
    procedure TForm1.GestionException(E : Exception);
    begin
      //Je LOG dans un fichier toutes les exceptions rencontrées
      ShowMessage('Sauvegarde de l''erreur:' + E.Message);
     
      if E is ExceptionGrave then
      begin
        with ExceptionGrave(E) do
        begin
          ShowMessage('Fermeture du logiciel'+ #10#13 +
            'Erreur:' + IntToStr(ErrorCode));
     
          //Je LOG dans un autre fichier les exeptions graves
          ShowMessage('Sauvegarde du numéro d''erreur:' + IntToStr(ErrorCode));
     
          //Ferme le programme
          Application.Terminate;
        end;
      end
      else
        ShowMessage('Exception pas grave');
    end;
    Merci d'avance

  10. #10
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    Tu veux absolument un code global pour gérer toutes les exceptions, cela peut-être utile, mais pourquoi ne pas traiter en amont les exeptions, dans un programme qui doit avoir une robutesse à toute épreuve, je ne comprends pas cette logique de vouloir provoquer l'arrêt de programme, alors qu'il vaudrait mieux déclencher des mécanismes de secours comme avertir un responsable d'une anomalie, par mail, par alerte sonore (utile si c'est un ordi isolé où il n'y a pas d'utilisateur en permanence), arrêter les machines ou le circuit de production,...

    Essaye d'empêcher le déclenchement d'exception !
    Mieux vaut gérer pour chaque cas, une correction, et si la correction est impossible, là passer en mode "défaillance irrémédiable"

    Le ShowMessage restera afficher, ton application restera bloquer indéfiniment si personne ne vient la voir !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  11. #11
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    115
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 115
    Par défaut
    Le programme ne vas fonctionner que pendant quelques minutes (-5 minutes) avec un utilisateurs devant.
    Stopper mon programme en cas de problème, m'évite surtout de fausser des lignes importantes de la base de données.

    Âpres je conçois tout a fait le principe de gérer localement une exception, voir même de ne pas en déclencher.
    Mais si je suis dans le cas, où je manipule des fonctions de plusieurs librairies, je ne peux pas gérer localement chaque appel...

Discussions similaires

  1. [Debutant] Exceptions non traitées
    Par L. Sierra dans le forum Langage
    Réponses: 4
    Dernier message: 24/09/2006, 19h16
  2. Réponses: 2
    Dernier message: 11/05/2006, 11h34
  3. [C#] exception non gérée
    Par zorglub88 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 27/03/2006, 16h28
  4. Réponses: 4
    Dernier message: 14/02/2005, 19h41
  5. [thread] Exception non catchée
    Par mammistegon dans le forum Concurrence et multi-thread
    Réponses: 3
    Dernier message: 22/11/2004, 21h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo