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

C++/CLI Discussion :

Problème dans l'utilisation de saveFileDialog


Sujet :

C++/CLI

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    243
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 243
    Par défaut Problème dans l'utilisation de saveFileDialog
    Bonjour,

    J'ai véveloppé un programme qui écrit des données dans un fichier temporaire nommé "output.tmp" ..

    Quand on ferme le programme, je donne à l'utilisateur la possibilité de sauvegarder ces données en renommant le fichier et j'utilise le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if (saveFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
    {
    	String^ file_name = gcnew String("");
    	file_name = saveFileDialog1->FileName::get();
    	File::Move ("output.tmp",file_name);
    }
    Cela fonctionne si le nom du fichier donné est nouveau.
    Par contre si le fichier existe déjà, ça plante même si on a répondu qu'on accepte de remplacer le fichier.

    J'ai donc rajouté :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     if (saveFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
    {
    	String^ file_name = gcnew String("");
    	file_name = saveFileDialog1->FileName::get();
    	if (File::Exists (file_name)) File::Delete (file_name);
    	File::Move ("output.tmp",file_name);
    }
    Et ça plante toujours comme si l'instruction rajoutée n'était pas exécutée ...

    J'ai eu l'impression que Windows exécute le Move avant le Delete ...

    Pour m'en assurer j'ai fait une horreur du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if (saveFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
    {
            String^ file_name = gcnew String("");
    	file_name = saveFileDialog1->FileName::get();
    	if (File::Exists (file_name)) File::Delete (file_name);
    	a: if (File::Exists (file_name)) goto a;
    	File::Move ("output.tmp",file_name);
    }

    Et là ça marche

    J'ai donc plusieurs questions:

    1- Pourquoi avec la forme simple le saveFileDialog ne détruit pas lui même le fichier existant quand on lui dit qu'on accepte le remplacement?

    2- Pourquoi le Move s'exécute apparemment avant le Delete?

    3- Comment faire ça proprement?


    Merci d'avance à ceux qui pourront éclairer ma pauvre lanterne.

    Bonne journée.

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 479
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 479
    Par défaut
    Comme je n’ai jamais été doué pour les devinettes, moi je triche, je regarde la solution écrite à l'envers dans les Carambars.

    Trêves de mise en boite.

    Quand un programme plante, il y a un message d'erreur qui permet très souvent de trouver la raison initiale du problème.

    Donc, pouvez-vous nous donner le message d'erreur lors du plantage ?

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    243
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 243
    Par défaut
    Bonjour Paul,

    Of course, with pleasure ...

    Dans les cas 1 et 2, je reçois le message suivant:

    Unhandled exception.... bla bla bla ..

    System.IO.IOException: Impossible de créer un fichier déjà existant.

    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.IO.__Error.WinIOError()
    at System.IO.File.Move(String sourceFileName, String destFileName)
    at ....Form1.Appli_Close() in c:\........\form1.h:line 2230
    at ....Form1.Form1_FormClosing(Object sender, FormClosingEventArgs e) in c:\.........\form1.h:line 2209
    at System.Windows.Forms.Form.OnFormClosing(FormClosingEventArgs e)
    at System.Windows.Forms.Form.WmClose(Message& m)
    at System.Windows.Forms.Form.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

    La ligne 2230 est la ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    File::Move ("output.tmp",file_name);
    qui se trouve juste après :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    File::Delete (file_name);
    Ce qui m'a fait penser qu'au moment où le Move s'exécute, le Delete n'est pas encore exécuté ...

    Et dans le cas 3, en rajoutant l'horrible boucle d'attente, ça marche sans problème mais je trouve ça horrible ...

    On dirait qu'il faut laisser le temps à Windows de détruire l'ancien fichier avant de faire le Move ..

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 479
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 479
    Par défaut
    Sans certitudes, je pense à un problème de handler de fichier non fermé, associé à des actions d'"IO pending".

    Je pense que votre "horrible" boucle finira par activer le garbage collector du Runtime.
    Le garbage collector scanne les références de variable et voit qu'une variable File n'est plus accessible.
    Il enclenche le Finalize de l'objet.
    Le Finalize d'un objet File ne fait que fermer/libérer l'handler de fichier Kernel du fichier.
    En libérant le handler de fichier, le garbage collector permet aux autres actions "pending" sur le fichier de s'effectuer.
    Un Delete de fichier est l'action "pending" par excellence, elle n'est exécutée que très rarement dans la foulé de la demande. On peut même attendre un reboot de la machine pour qu'il soit effectif, cas extrêmement fréquent dans les installations de programmes "résidants" (la base de registre est un précieux allier du système dans ce cas).

    Donc, le moyen pour infirmer ou affirmer mon hypothèse, c'est de vérifier que votre programme (ou un autre) n'a pas de handler sur le fichier au moment du Delete (via un outil type Process Explorer).

    Si c'est bien le cas, c'est que vous gérez mal le cycle de vie de vos objets de type File.

    Il ne faut pas croire le discoure marketing sur le miracle du garbage collector, tout fichier ouvert doit être explicitement fermé (le mot clé "using" du C# est même une excellente initiative dans ce sens).

    La fonctionnalité que vous présenté ressemble fort à des logs et .NET disposent d'outil bien plus puissant et simple que les primitives de fichier pour faire cela.

    Entreprise Library (EntLib) dispose d'un ensemble de fonctionnalité de log énorme. Il gérera automatiquement le rolling des fichiers de logs, et cela sans la moindre ligne dans votre code autre que des primitives d'envoie de messages génériques.

Discussions similaires

  1. Réponses: 4
    Dernier message: 13/04/2008, 00h01
  2. Problème dans l'utilisation d'un tableau
    Par NoiBe dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 16/05/2007, 16h19
  3. problème dans l'utilisation de g_access()
    Par bit_o dans le forum GTK+ avec C & C++
    Réponses: 18
    Dernier message: 02/03/2007, 14h57
  4. Problème dans l'utilisation du WebBrowser
    Par MCShiff dans le forum Windows Forms
    Réponses: 2
    Dernier message: 10/01/2007, 12h52
  5. probléme dans l'utilisation d'un tableau
    Par hamoudasafira dans le forum C++
    Réponses: 10
    Dernier message: 13/12/2006, 08h50

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