Problème avec la fonction MoveFile [Résolu]

Problème avec la fonction MoveFile [Résolu] - C++ - Programmation

Marsh Posté le 27-10-2004 à 08:47:14    

Bonjour, je programme sous Visual C++ 6, et dans une fenêtre (MFC) j'ai toute une série de boutons permettant de modifier le nom d'un répertoire, ce qui se fait à l'aide du code ci-dessous.
 

Code :
  1. char repertoire1[1024];
  2. strcpy(repertoire1,repertoire_saga);
  3. construire_chemin(repertoire1,0);
  4. char repertoire2[1024];
  5. strcpy(repertoire2,repertoire_saga);
  6. c_saisir.type_saisie = 2;
  7. m_liste_clients.GetText(m_liste_clients.GetCurSel(),c_saisir.valeur_a_modifier);
  8. c_saisir.DoModal();
  9. strcat(repertoire2,c_saisir.m_nouvelle_valeur);
  10. strcat(repertoire2,"\\" );
  11. if(MoveFile(repertoire1,repertoire2))
  12. {
  13.  lister_clients();
  14.  m_liste_clients.SetCurSel(m_liste_clients.FindStringExact(0,c_saisir.m_nouvelle_valeur));
  15.  OnSelchangeListeClients();
  16.  GetDlgItem(IDC_LISTE_VILLES)->SetFocus();
  17. }
  18. else
  19. {
  20.  MessageBox("Le client n'a pas pu être renommé","Erreur",MB_ICONSTOP);
  21. }


 
Le problème qui se pose est que celà fonctionne très bien sous Windows98, mais que sous XP j'ai toujours le message "Le client n'a pas pu être renommé". Donc il semble que ça bloque au niveau du MoveFile, mais je n'arrive pas à trouver pourquoi (j'ai vérifié, les répertoires ne sont pas en lecture seule)...


Message édité par Alkor2001 le 29-10-2004 à 10:34:31

---------------
J'aime pas Apple...
Reply

Marsh Posté le 27-10-2004 à 08:47:14   

Reply

Marsh Posté le 27-10-2004 à 09:01:45    

Si:
1. tu nous donnais le contenu de repertoire1 et repertoire2 tel que passé à MoveFile.
2. Tu récupérais GetLastError pour nous dire ce qui coince.
3. Tu utilisais std::string ou CString pour gérer tes chaînes de caractères, parce les char toto[1024], ça fait quelques années qu'on en fait plus...
 
Ca serait plus simple à voir...


Message édité par Lam's le 27-10-2004 à 09:02:47
Reply

Marsh Posté le 27-10-2004 à 09:50:08    

Lam's a écrit :

Si:
1. tu nous donnais le contenu de repertoire1 et repertoire2 tel que passé à MoveFile.
2. Tu récupérais GetLastError pour nous dire ce qui coince.
3. Tu utilisais std::string ou CString pour gérer tes chaînes de caractères, parce les char toto[1024], ça fait quelques années qu'on en fait plus...
 
Ca serait plus simple à voir...


 
Alors:
1. repertoire1: "c:\Saga\Donnees\ancient nom client", repertoire2: "c:\Saga\Donnees\nouveau nom client"
2. J'ai honte, je n'avais pas pensé au GetLastError...  :pfff:  Donc l'erreur est: "Error 32: Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus". Ce qui est emmerdant c'est qu'il n'y a pas d'autre processus accédant à ce répertoire en même temps, et que le problème n'intervient pas sous 98...
3. Je suis passé au CString depuis quelque temps déjà, mais cette partie du programme est assez ancienne et je n'ai pas eu le temps de modifier les char[] pour les remplacer par des CString...


---------------
J'aime pas Apple...
Reply

Marsh Posté le 27-10-2004 à 11:07:16    

Alkor2001 a écrit :

Ce qui est emmerdant c'est qu'il n'y a pas d'autre processus accédant à ce répertoire en même temps, et que le problème n'intervient pas sous 98...


 
Dans Windows 2000/XP un dossier est considéré comme utilisé par une application son "dossier en cours" pointe dessus (par ex si tu as ouvert un fichier dans ce dossier, il faut que tu quittes l'application qui a ouvert le fichier, que l'application fasse un SetCurrentDirectory sur un autre dossier, ou que tu ouvres un autre fichie).
C'est assez lourd :o


Message édité par antp le 27-10-2004 à 11:07:22
Reply

Marsh Posté le 27-10-2004 à 11:31:52    

antp a écrit :

Dans Windows 2000/XP un dossier est considéré comme utilisé par une application son "dossier en cours" pointe dessus (par ex si tu as ouvert un fichier dans ce dossier, il faut que tu quittes l'application qui a ouvert le fichier, que l'application fasse un SetCurrentDirectory sur un autre dossier, ou que tu ouvres un autre fichie).
C'est assez lourd :o


 
 :ouch: Ah ok!
Merci beaucoup, je j'avais pas pensé à un truc aussi lourd! Je regardais plutôt du côté de la lecture seule... Et en effet, le dossier en cours pointe directement sur le répertoire que je veux modifier, donc maintenant je sais ce qu'il me reste à faire!


---------------
J'aime pas Apple...
Reply

Marsh Posté le 27-10-2004 à 16:17:06    

Bon bah, j'avais mis "Résolu" dans le titre, mais je le retire...
 
J'ai essayé plusieurs trucs à base de SetCurrentDirectory pointant sur d'autres répertoires (même un SetCurrentDirectory("c:\\" ), j'ai essayé d'ouvrir un autre fichier, mais rien n'y fait, je me retrouve toujours avec cette saloperie d'erreur32 en cas de MoveFile...


---------------
J'aime pas Apple...
Reply

Marsh Posté le 27-10-2004 à 16:23:18    

Tu es 100% sûr que tu n'as pas de fichier ouvert dedans (via ton appli), ou l'exploreur qui pointe dessus, ou même un contrôle qui t'affiche le contenu du répertoire ?
 
D'autre part, Win98 avait une gestion plus "légère" des accès concurrents, donc le fait que ça fonctionne dessous ne veut rien dire...

Reply

Marsh Posté le 27-10-2004 à 16:54:30    

Alkor2001 a écrit :

Bon bah, j'avais mis "Résolu" dans le titre, mais je le retire...


 
les trucs entre crochets faut pas les mettre en début de titre, sinon le nom de la sous-catégorie ne s'ajoute plus automatiquement :o


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 27-10-2004 à 17:19:09    

antp a écrit :

les trucs entre crochets faut pas les mettre en début de titre, sinon le nom de la sous-catégorie ne s'ajoute plus automatiquement :o


 
Oups, désolé...  :sweat:  
 
Et sinon, un conseil pour corriger mon problème?  :ange:  
(j'ai mis en place un truc bourrin qui passe par du CreateDirectory et du CopyFile, mais ça ne me plait pas du tout...)


---------------
J'aime pas Apple...
Reply

Marsh Posté le 27-10-2004 à 17:23:00    

T'es sûr que t'as pas un chti handle qui traine sur ton fichier dans ton rep ?
Ou simplement que tu as les droits ?
Lance ton exe mais sans tenter de changer le dir. Pendant qu'il tourne, avec explorer, essaye de changer le nom du dir, pour voir...


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 27-10-2004 à 17:23:00   

Reply

Marsh Posté le 28-10-2004 à 12:12:22    

HelloWorld a écrit :

T'es sûr que t'as pas un chti handle qui traine sur ton fichier dans ton rep ?
Ou simplement que tu as les droits ?
Lance ton exe mais sans tenter de changer le dir. Pendant qu'il tourne, avec explorer, essaye de changer le nom du dir, pour voir...


 
Pour le handle, je ne crois pas, et j'ai tous les droits nécessaires, mon programme est exécuté soit sur des ordinateurs en local, soit sur un serveur avec les droits complets sur son répertoire.
 
Je vais expliquer de mieux expliquer mon bordel:
J'ai une CListBox que je remplis avec les noms des clients (correspondant chacun à un répertoire) avec la fonction:
 

Code :
  1. void CGestionFichiers::lister_clients()
  2. {
  3. WIN32_FIND_DATA fd;
  4. HANDLE handle;
  5. char repertoire[1024];
  6. strcpy(repertoire,repertoire_saga);
  7. SetCurrentDirectory(repertoire);
  8. effacer_clients();
  9. handle=FindFirstFile("*.*",&fd);
  10. while(handle!=INVALID_HANDLE_VALUE)
  11. {
  12.  if(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
  13.  {
  14.   if(fd.cFileName[0]!='.')
  15.   {
  16.    m_liste_clients.AddString(fd.cFileName);
  17.   }
  18.  }
  19.  if(!FindNextFile(handle,&fd))
  20.   handle=INVALID_HANDLE_VALUE;
  21. }
  22. FindClose(handle);
  23. SetDlgItemText(IDC_NB_MATS,"" );
  24. }


 
Ensuite, j'ai une fonction OnSelChangeClient() qui affiche les sous-répertoires de ce client et qui est activée dès qu'on clique sur un nom de client dans la CListBox.
 

Code :
  1. void CGestionFichiers::OnSelchangeListeClients()
  2. {
  3. char repertoire[1024];
  4. strcpy(repertoire,repertoire_saga);
  5. construire_chemin(repertoire,0);
  6. SetCurrentDirectory(repertoire);
  7. lister_villes();
  8. char tmp[128];
  9. m_liste_clients.GetText(m_liste_clients.GetCurSel(),tmp);
  10. strcpy(back_client,tmp);
  11. activer_boutons(0);
  12. }
  13. void CGestionFichiers::construire_chemin(char *chemin,int progression)
  14. {
  15. char tmp[128];
  16. m_liste_clients.GetText(m_liste_clients.GetCurSel(),tmp);
  17. strcat(chemin,tmp);
  18. strcat(chemin,"\\" );
  19. if(progression>=1)
  20. {
  21.  m_liste_villes.GetText(m_liste_villes.GetCurSel(),tmp);
  22.  strcat(chemin,tmp);
  23.  strcat(chemin,"\\" );
  24. }
  25. }


 
(lister_villes() est comme lister_clients(), sauf qu'on remplit une autre CListBox)
 
A côté de ça, j'ai un bouton permettant de modifier le nom du client sélectionné, dont le code est donné dans mon 1er post.
 
J'ai testé sous l'explorateur, je peux modifier le nom d'un client manuellement, sauf si je le sélectionne au préalable dans la CListBox...
 
J'ai essayé plein de trucs différents, du style faire un SetCurSel(-1) suivi d'un OnSelChangeListeClient() sur la liste des clients juste avant de tenter le MoveFile, ce qui devrait mettre le "focus" de Windows sur un autre répertoire client, mais non, même comme ça il continue de m'afficher que celui que je veux renommer est en cours d'utilisation...
 
Sinon, il y a d'autres fonctions permettant de renommer un répertoire? (enfin à mon avis ça ne fonctionnerait pas mieux, mais on ne sait jamais...)
 
 


---------------
J'aime pas Apple...
Reply

Marsh Posté le 28-10-2004 à 13:15:02    

Dans mon soft qui renomme des fichiers & dossiers (Ant Renamer) j'utilise MoveFile et je n'ai jamais eu de problème de ce genre...


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Marsh Posté le 28-10-2004 à 15:06:50    

As tu tester de renommer depuis l'explorer alors que ton soft tourne ?
Sinon lance filemon pour traquer les accès aux fichiers, et process explorer pour lister les handles détenus par ton appli.
http://www.sysinternals.com/ntw2k/source/filemon.shtml
http://www.sysinternals.com/ntw2k/ [...] cexp.shtml


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 28-10-2004 à 16:03:00    

HelloWorld a écrit :

As tu tester de renommer depuis l'explorer alors que ton soft tourne ?
Sinon lance filemon pour traquer les accès aux fichiers, et process explorer pour lister les handles détenus par ton appli.
http://www.sysinternals.com/ntw2k/source/filemon.shtml
http://www.sysinternals.com/ntw2k/ [...] cexp.shtml


 
Oui j'ai testé, et ça ne fonctionne pas si le client que je veux renommer dans l'explorer est sélectionné dans la CListBox de mon programme.
 
Je vais essayer filemon et process explorer pour voir, merci  :hello: !


---------------
J'aime pas Apple...
Reply

Marsh Posté le 28-10-2004 à 17:55:26    

Donc c'est bien un probleme dans ton code...


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 29-10-2004 à 09:07:04    

HelloWorld a écrit :

Donc c'est bien un probleme dans ton code...


 
Ca je m'en doute!   :D  
 
Y a un truc bizarre que je vois apparaître avec Filemon, c'est que j'ai des FindOpen quand je clique sur un nom de client dans la liste (ça c'est normal), mais aucun FindClose! Ce n'est qu'à l'extinction du programme que j'ai une série de Kernel32:FindClose qui apparaît...
C'est bizarre, parce que les seuls accès que je fais aux répertoires se font par "SetCurrentDirectory(repertoire);" ou "handle=FindFirstFile("*.*",&fd);" toujours suivi d'un "FindClose(handle);" ...
 
C'est de là que vient mon problème, non?
 
EDIT: Bon ok, en fait c'est ma fonction de parcours du contenu d'un répertoire qui est mal foutue, il semble que ne je puisse pas faire de FindClose sur un handle qui a pour valeur INVALID_HANDLE_VALUE...  :sweat: (dit comme ça ça parait logique, mais je n'y avais pas du tout fait attention, surtout que ça paraissait fonctionner)


Message édité par Alkor2001 le 29-10-2004 à 09:21:59

---------------
J'aime pas Apple...
Reply

Marsh Posté le 29-10-2004 à 10:35:54    

Bon bah c'était bien ça le problème!
En utilisant le FindFirstFile et le FindClose comme la MSDN le préconise, je n'ai plus ce problème, merci pour votre aide!  :hello:


---------------
J'aime pas Apple...
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed