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

Langage Delphi Discussion :

GetLastError avec package d'exécution


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Homme Profil pro
    Chef de projets
    Inscrit en
    Août 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2008
    Messages : 127
    Points : 195
    Points
    195
    Par défaut GetLastError avec package d'exécution
    Bonjour,

    J'ai un code qui fonctionnait bien jusqu'à aujourd'hui. Pour de multiple raisons, j'utilisais un exe incluant tous les BPL.
    Maintenant j'ai décidé de construire mon projet en cochant la case "lié les packages d'execution".

    Par contre ce code ne marche plus. Le GetLastError retourne toujours "0" au lieu, par exemple de "32".

    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
     
    procedure TForm1.Button1Click(Sender: TObject);
    Var
       Stream: TStream;
       iError : integer;
    begin
       Stream := nil;
       iError := -1;
       try
          try
             Stream := TFileStream.Create('d:\toto.docx', fmOpenRead);
          except
             begin
                iError := GetLastError;
             end;
          end;
       finally
          if Assigned(Stream) then
             Stream.Free;
       end;
     
     
       showmessage('Erreur : ' + inttostr(iError));
     
     
    end;
    Peux importe les packages que je mets, dès qu'ils sont activés, je n'ai plus mon code d'erreur

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 831
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 831
    Points : 13 579
    Points
    13 579
    Par défaut
    Ca ne peut pas marcher, même sans bpl.

    GetLastError renvoie le dernier code d'erreur ET le remet à 0.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    begin
      SetLastError(999);
      ShowMessage(IntToStr(GetLastError)); //999 au 1er appel
      ShowMessage(IntToStr(GetLastError)); //0 au deuxième
    end;
    Et puisque TFileStream génère l'éventuelle exception sur OpenFile en récupérant l'erreur par GetLastError, tu ne peux plus l'utiliser dans ton gestionnaire d'exception.

    Deuxième chose, l'objet n'est pas instancié si une exception survient dans son constructeur. Ce try..finally est soit inutile, soit mal placé.
    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
    procedure TForm1.Button1Click(Sender: TObject);
    Var
       Stream: TStream;
    begin
      try
        Stream := TFileStream.Create('d:\toto.docx', fmOpenRead);
     
        try
          ...
        finally
          Stream.Free;
        end;
     
      except
        on E:Exception do
          MessageDlg(E.Message, mtError, [mbOk], 0);
      end;
    end;

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 710
    Points : 25 593
    Points
    25 593
    Par défaut
    Dommage, le EFOpenError ne contient pas le code d'erreur mais il contient au moins le message détaillé sur le principe expliqué par AndNotOr

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
          except
             on EFOE: EFOpenError do
                sError := EFOE.Message;
          end;

  4. #4
    Membre habitué
    Homme Profil pro
    Chef de projets
    Inscrit en
    Août 2008
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2008
    Messages : 127
    Points : 195
    Points
    195
    Par défaut
    Je ne suis pas sûr de comprendre votre explication sur le GetLastError. Ce que je crois comprendre, c'est que vous me dite que le GetLastError est déjà appelé dans le gestionnaire d'exception du TFileStream.Create.

    Essayer le projet sans cocher les BPL et vous verrez que vous aurez le code "32" qui va ressortir. Donc pourquoi n'est il pas remis à 0 dans ce cas ?

    on EFOE: EFOpenError do
    sError := EFOE.Message;
    Effectivement on se rapproche d'une solution, mais sans être sûr de la cause du problème. Le message ne sera pas identique sur les machines étrangères.

    Je suis d'accort sur le try except et la construction petit projet fait à a va vite pour le forum

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 710
    Points : 25 593
    Points
    25 593
    Par défaut
    GetLastError gère une erreur par thread, normalement le BPL se comporte un peu comme une DLL et entre un EXE et DLL, cela partage le même "LastError"
    Sur XE2, j'ai bien le comportement que tu observes

    Pour moi GetLastError ne remet pas à Zéro dans tous les cas !
    J'ai l'impression que GetLastError ne remet à zéro que si c'est le module appelant qui lit la valeur, du moins c'est une observation et un comportement aussi variable n'a rien d'enchanteur :
    une DLL utilise SetLastError puis lit GetLastError, il y a une remise à zéro
    un EXE utilise SetLastError puis lit GetLastError, il y a une remise à zéro (voir code de AndNotOr)
    une DLL utilise SetLastError puis l'EXE appelant lit GetLastError, il n'y a pas de remise à zéro parce que ce n'est pas le même module entre le Set et le Get
    Le BPL étant une sorte de DLL à la sauce de Borland, cela s'applique probablement

    Dans notre exemple, la DLL qui définie LastError c'est kernel32 et l'EXE lit le GetLastError, et peut le lire autant de fois que souhaité
    Si l'on passe en mode BPL, la DLL kernel32 définie le LastError, le BPL lit le GetLastError (et là faudrait faire son propre BPL pour tester si il y a reset ou pas) et enfin l'EXE lui c'est trop tard pour lui pour relire le GetLastError

    En débogage, je perds le GetLastError au niveau de _RaiseExcept CALL RaiseList quelque par dans KERNELBASE.TlsGetValue ?
    Ce chemin n'est emprunté qu'en mode BPL séparé, en mode intégré, cela passer par @GetTls et cela ne touche pas "LastError"

    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
    Var
       Stream: TStream;
       iError, iError2 : integer;
    begin
       Stream := nil;
       iError := -1;
       iError2 := -1;
       try
          try
             Stream := TFileStream.Create('d:\toto.docx', fmOpenRead);
          except
             on E: Exception do
             begin
               iError := GetLastError;
               iError2 := GetLastError; // il est toujours défini
             end;
          end;
       finally
          if Assigned(Stream) then
             Stream.Free;
       end;
     
     
       showmessage('Erreur : ' + inttostr(iError) + '  : ' + inttostr(iError2));
     
    end;

  6. #6
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 831
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 831
    Points : 13 579
    Points
    13 579
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    GetLastError renvoie le dernier code d'erreur ET le remet à 0.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    begin
      SetLastError(999);
      ShowMessage(IntToStr(GetLastError)); //999 au 1er appel
      ShowMessage(IntToStr(GetLastError)); //0 au deuxième
    end;
    Effectivement, je dis des conneries
    C'est ShowMessage ici qui le force à 0.

  7. #7
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 972
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 972
    Points : 15 440
    Points
    15 440
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    GetLastError renvoie le dernier code d'erreur ET le remet à 0.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    begin
      SetLastError(999);
      ShowMessage(IntToStr(GetLastError)); //999 au 1er appel
      ShowMessage(IntToStr(GetLastError)); //0 au deuxième
    end;
    Effectivement, je dis des conneries
    C'est ShowMessage ici qui le force à 0.
    Pas d'accord, d'un point de vue sémantique : ShowMessage ne force rien du tout, c'est juste que le 1er ShowMessage s'exécute correctement en affichant 999, ne génère pas d'erreur, donc, et du coup le 2nd ShowMessage affiche 0 parce que GetLastError remonte 0 parce qu'il n'y a pas eu d'erreur à l'instruction précédente.

  8. #8
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 831
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 831
    Points : 13 579
    Points
    13 579
    Par défaut
    Et comment pourrait-il valoir 0 s'il n'y a pas de SetLastError(0) quelque part ?

  9. #9
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 972
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 972
    Points : 15 440
    Points
    15 440
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Et comment pourrait-il valoir 0 s'il n'y a pas de SetLastError(0) quelque part ?
    Ben je sais pas trop, mais il se trouve que j'ai dans un coin le Dialogs.pas de D2005 et n'ai rien trouvé dedans à partir de ShowMessage et jusqu'à function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons): TForm;...

    En fait, je pense que le fonctionnement interne et de bas niveau est un peu comme ce qu'on voit sous Linux : toute commande (que ce soit un binaire stand-alone ou une fonction [bien écrite !] dans un script) renvoie un code de fin d'exécution, libre à l'utilisateur de le lire ou pas.
    Dans un script, je peux par exemple écrire cp src dst (et je vais à la catastrophe) ou err=cp src dst et ensuite tester la valeur de err et agir en conséquence.
    Un peu ce que fait GetLastError, nan ?

  10. #10
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 831
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 831
    Points : 13 579
    Points
    13 579
    Par défaut
    Il y a plusieurs appels pouvant influer sur le code d'erreur : GetFileVersionInfoXXX, LoadString, GetModuleFileName, ce dernier au minimum forçant (je persiste) ERROR_SUCCESS (0).

Discussions similaires

  1. Réponses: 6
    Dernier message: 16/04/2007, 20h05
  2. [JNI]Execution d'une dll dans un jar avec package
    Par osopardo dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 01/09/2006, 12h50
  3. "Ouvrir avec" un Jar exécutable
    Par RisWaaq dans le forum Langage
    Réponses: 3
    Dernier message: 09/06/2006, 15h46
  4. Réponses: 2
    Dernier message: 08/06/2006, 16h49
  5. [ClassLoader] Chargement dynamique d'une classe -> problème avec packages !
    Par ymerej dans le forum API standards et tierces
    Réponses: 9
    Dernier message: 31/05/2006, 22h37

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