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 :

Exception dans un service windows


Sujet :

Langage Delphi

  1. #1
    Nouveau membre du Club
    Inscrit en
    Décembre 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 41
    Points : 36
    Points
    36
    Par défaut Exception dans un service windows
    bonjour,
    il y a plusieurs années j'ai développé un service windows en Delphi qui scrute un répertoire tous les 5 secondes (c:\dataExchange\DataIn), recherche un fichier nommé priority.csv.
    Si ce fichier existe, il ouvre ce fichier et lit tous les fichiers de données à traiter. (fichiers csv stockés dans le même répertoire)
    Le traitement consiste à charger des données en mémoiren les analyser et à lancer un exe en C++. (méthode CreateProcess et WaitForSingleObject) puis suppression du fichier d'entrée de données
    Une fois que toutes les données d'entrées sont traitées, le fichier priority.csv est supprimé.

    ce mécanisme marche parfaitement sauf de temps en temps avec le message d'erreur suivant dans une boite de dialogue:
    Impossible d'ouvrir le fichier "c:\DataExchange\DataIn\Priority.csv". Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus.

    Comment faire pour ne pas avoir de boite de dialogue qui bloque le process?
    J'ai analysé que c'est une exception de type EFOpenError qui est déclenchée sur la ligne suivante:

    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
    VAR
      List, Items                           : TStringList;
      I, J                                  : Integer;
     
    BEGIN
      {On crée dynamiquement la liste qui va contenir les lignes du fichier}
      List := TStringList.Create;
      TRY
        IF FileExists(FileName) THEN
        BEGIN
          {On charge le fichier}
          List.LoadFromFile(FileName); // Exception ici
     
          {On détruit les lignes vides ou commencant par #}
          IF EraseRow THEN
            CleanList(List);
     
          {On initialise le tableau}
          SetLength(CsvExtract.TabResult, 0, List.Count);
     
          {On fait toutes les lignes du fichier}
          FOR I := 0 TO List.Count - 1 DO
          BEGIN
            {On recupere les différents champ de la ligne}
            Items := RecupItems(List.Strings[I]);
     
            TRY
              {On définit la taille du tableau}
              IF High(CsvExtract.TabResult) < Items.Count THEN
                SetLength(CsvExtract.TabResult, Items.Count, List.Count);
     
              {On ajoute les lignes de la liste au tableau}
              FOR J := 0 TO Items.Count - 1 DO
                CsvExtract.TabResult[J, I] := Items.Strings[J];
            FINALLY
              Items.Free;
            END;
          END;
        END
        ELSE
          ShowMessage('Le chemin suivant : "' + FileName + '" n''est pas valide.');
      FINALLY
        {On détruit le tstringlist pour libérer la mémoire}
        List.Free;
      END;
    END;

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    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 577
    Points : 25 225
    Points
    25 225
    Par défaut
    utilise try except on EFOpenError autour du LoadFromFile !
    Tu ne connais pas le système d'exception de Delphi ? tu utilises pourtant try finally ???

    N'utilise pas ShowMessage, il y a une fonction de Log dans un TService qui permet d'ajouter des messages au journal d'évènement de windows !

    Sinon, tu pourrais réduire la conso de ton programme en utilisant FindFirstChangeNotification
    tu pourrais détecter le changement de taille du dossier contenant ton fichier !
    Cherche sur le forum, il y a plusieurs sujet concernant cette API ainsi que des sujets sur l'ouverture de fichier déjà en cours d'utilisation et comment détecter leur utilisation comme récupérer le Handle du process qui l'utilise ...

    Pense qu'avec des OS récents, utiliser un CreateProcess depuis un Service Windows peut s'avérer pénible !
    D'abord penser à l’interaction avec le bureau, ça c'est le cas depuis 2K au moins
    les droits d’exécution si ton service tourne sans session déjà ouverte, il faut lui affecter un login ayant les droits suffisants !
    Et pour Vista\Seven\2008, les choses se compliquent nettement !

  3. #3
    Nouveau membre du Club
    Inscrit en
    Décembre 2005
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 41
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    utilise try except on EFOpenError autour du LoadFromFile !
    Est-ce que une correction de ce type est adaptée?
    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
     
     VAR
      List, Items                           : TStringList;
      I, J                                  : Integer;
      lectureOk                            : boolean;
     
    BEGIN
      {On crée dynamiquement la liste qui va contenir les lignes du fichier}
      List := TStringList.Create;
      TRY
        IF FileExists(FileName) THEN
        BEGIN
          repeat
          try
             {On charge le fichier}
              List.LoadFromFile(FileName); // Exception ici
     
              lectureOk := 1;
              except
                on EFOpenerror do lectureOk :=0;
              end;
         until lectureOk =0;
     
          {On détruit les lignes vides ou commencant par #}
          IF EraseRow THEN
            CleanList(List);
    ...

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 577
    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 577
    Points : 25 225
    Points
    25 225
    Par défaut
    Tu vas boucler indéfiniment en cas d'erreur, mais c'est une idée si tu veux absolument lire le fichier
    Un Sleep serait utile, cela laisse le temps à l'autre processus d'écrire et de libérer le fichier, inutile de stresser l'OS !
    Tu peux aussi limiter le nombre de tentative à 5, puisque de toute façon, tu recommence toutes 5 secondes !
    Je dirais même que la boucle n'est pas utile, mais si ça te fait plaisir !

    Comme je le disais, si ton fichier "priority.csv" change de taille, utilise FindFirstChangeNotification pour le détecter, lorsque le fichier commence à changer de taille ou vient d'être créer, tu sais alors que le fichier est en cours d'utilisation, et lors qu'il n'y a plus de modification de taille, on peut supposer que l'autre processus a terminer et c'est à ce moment que tu tentes l'ouverture !

    cela me rappel le sujet Comment utiliser TTimer pour détecter un événement dans un répertoire ?

    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
     
          lectureOk := false;
          LectureTentative := 0;
          repeat
            try
              if LectureTentative > 0 then
                Sleep(1000);
     
               {On charge le fichier}
               List.LoadFromFile(FileName); // Exception ici
     
                lectureOk := true;
            except
              on EFOpenerror do 
              begin
                lectureOk := false;
                Inc(LectureTentative);
            end;
         until lectureOk or (LectureTentative >= 5);

Discussions similaires

  1. COM/ActiveX dans un service Windows
    Par Geoffrey5294 dans le forum Windows Forms
    Réponses: 0
    Dernier message: 05/11/2008, 16h08
  2. WCF hébergé dans un service - Windows Vista
    Par Aurélien19 dans le forum Windows Communication Foundation
    Réponses: 3
    Dernier message: 11/10/2008, 14h00
  3. DBexpress dans un service windows
    Par jmmazie dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 30/09/2008, 12h12
  4. lancement sqlloader dans un service Windows
    Par DrZoune dans le forum C#
    Réponses: 7
    Dernier message: 05/02/2008, 10h19
  5. Réponses: 5
    Dernier message: 28/12/2007, 09h56

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