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++ Discussion :

SHFileOperation et copie multiple


Sujet :

C++

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut SHFileOperation et copie multiple
    Bonjour.

    J'utilise la méthode SHFileOperation(), afin de copier des fichiers d'une partition A vers une partition B. Quand il s'agit de copier un dossier spécifique, par exemple "C:\DEV", tout va bien. Quand il s'agit de copier des fichiers particuliers, du type "C:\*.txt" ou même "C:\*.txt", tout fonctionne.

    Le soucis, c'est que je souhaiterais copier tout le contenu d'un disque. C'est à dire tout le C:\ par exemple. Après de multiples essais, je n'arrive pas a copier tout depuis la racine d'un disque.

    Je me suis donc orienter vars un listing de tous les dossiers présents à la racine, puis une copie multiple à l'aide de SHFileOperation() toujours.

    Malheureusement, je rencontre quelques difficultés concernant la copie dite multiple. Voila ce que dit la doc MSDN concernant ce point :

    Each file name is terminated by a single NULL character. The last file name is terminated with a double NULL character ("\0\0") to indicate the end of the buffer.
    Donc, si je met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string source = "C:\\*\0\0"
    Ca va me copier la totalité des fichiers de C:\. Par contre, si je met
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string source = "C:\\*\0C:\\DEV\0\0"
    ,et bien ca ne me copie, encore, que les fichiers de C:\, et ca ne prend pas en compte le répertoire DEV.

    Qu'est ce qui pose problème ?

    Cordialement,
    PKO
    Quand c'est trop, c'est pas bon !

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Essaie plutôt ceci:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    string source("C:\\*\0C:\\DEV\0\0", 13);
    Et encore, il est possible que ceci suffise:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    string source("C:\\*\0C:\\DEV\0", 12);
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Bonjour Médinoc, et merci.

    Malheureusement, rien n'y fait, ça me copie bien les fichiers, mais pas le repertoire \DEV. Je poste mon code, peut être que l'erreur est ailleurs :

    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
    void CopyData()
    {
    	string src = "P:\\*\0P:\\DEV\0\0";
    	string dst = "C:\\TEST\0\0"
    
    //	string source("P:\\*\0P:\\DEV\0", 12); // Résultat identique
    
    
    
    
    
    	// Configuration de la copie
    	SHFILEOPSTRUCTA fop2;
    	fop2.hwnd=NULL;
    	fop2.wFunc=FO_COPY;
    	fop2.pFrom=src.c_str();					
    	fop2.pTo=dst.c_str();					
    	fop2.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_SIMPLEPROGRESS;
    	fop2.fAnyOperationsAborted = 0;
    	fop2.hNameMappings = NULL;
    	fop2.lpszProgressTitle = "Test"
    
    	// Lancement de la copie
    	SHFileOperationA(&fop2);
    }
    J'ai mis en gras les éléments que qui peuvent être des détails important.

    Pour information, je suis sous Windows XP, et je boss avec API Windows et Qt. Je suis preneur de toutes informations utiles.

    Cordialement,
    PKO
    Quand c'est trop, c'est pas bon !

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Je ne vois pas ma correction dans ce code. Sache que sans, c'est sûr de ne pas marcher, car le constructeur std::string::string(char*) s'arrête au premier caractère nul. Tu dois utiliser un constructeur de string qui prend la vraie longueur en paramètre.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Oui, ta modification n'apparait pas dans le code. J'ai mis ma première version. J'ai bel et bien testé ce que tu as expliqué dans ton précédent poste, hélas, le résultat reste le même : Le programme copie bien les fichiers, mais pas le repertoire.

    Étant donné que le code posté me fourni le même résultat avec, ou sans la modification, je n'ai pas jugé utile de le faire apparaitre (loin de moi l'idée que ta remarque est inutile bien sur !)

    Cordialement,
    PKO
    Quand c'est trop, c'est pas bon !

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    As-tu un retour d'erreur de la fonction ?

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Bonjour.

    L'appel de SHFileOperationA(&fop2); me renvoi la valeur 5. D'apres MSDN, i lest indiqué que : "Returns zero if successful; otherwise nonzero."

    GetlastError() me renvoi la valeur 6 : The handle is Invalid.

    Malgré cela, mes fichiers sont correctement copiés. Les répertoires, non.

    Je rappel tout de même que mon objectif est de copier tout le contenu d'une partition (p.ex. C:\). N'arrivant pas a copier une partition, je me suis orienté vers la copie de plusieurs dossiers. Si vous avez une idée de la manière dont je dois m'y prendre pour copier une partition depuis la racine, je prend .

    Cordialement,
    PKO
    Quand c'est trop, c'est pas bon !

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Altess Voir le message
    Bonjour.

    L'appel de SHFileOperationA(&fop2); me renvoi la valeur 5. D'apres MSDN, i lest indiqué que : "Returns zero if successful; otherwise nonzero."

    GetlastError() me renvoi la valeur 6 : The handle is Invalid.
    Je pense que c'est ça à creuser. Le début de la copie doit réussir puis à un moment, il y a échec. C'est certainement pour cela que ton 2 paramètres n'a pas l'air d'être pris en compte.
    N'existe-t-il pas des fichiers systèmes ou à accès limités qui ne pourraient pas être copié ? Ce qui ferait échouer ta fonction ?

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Je n'en suis qu'au stade des tests. Je simplifie donc au maximum, et je prend de simple fichiers textes et des dossiers tout a fait classiques.

    Ce qui me semble bizarre, c'est que si je fait une copie indépendante (Uniquement les fichiers, ou bien uniquement le repertoire) et bien ça fonctionne. Mais les 2 en même temps, c'est l'échec. En fouinant sur différents forums, je suis tombé sur des cas similaires aux miens. Mais toujours sans réponse ...

    Cordialement,
    PKO
    Quand c'est trop, c'est pas bon !

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    J'ai fait un test, en copiant non pas un fichier et un repertoire, mais en copiant 2 types de fichiers différents :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    string source("P:\\*.txt\0P:\\*.bat\0\0", 19);
    Dans P:\ j'ai placé un bat, un txt, et un iso.
    Lancement de l'application, code retour de la méthode : 0

    Et seul les txt et les bat ont été copié. Serait-ce ma notation de repertoire qui est erronée ?
    Quand c'est trop, c'est pas bon !

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Altess Voir le message
    Serait-ce ma notation de repertoire qui est erronée ?
    Bonne question (nous regardions tous le doigt ?) :
    Quid avec ça : "P:\\*\0P:\\DEV\\\0"

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Arf, ascenseur émotionnel. Ca fonctionne pas mieux :-(

    Edit -> Bon, j'ai testé un truc alakon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string source("P:\\DEV\0P:\\*\0\0", 13);
    au lieu de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string source("P:\\*\0P:\\DEV\0\0", 13);
    Résultat : Ca me copie bien tout, fichier et dossier. Mais ca me renvoi toujours erreur 5 ...
    Quand c'est trop, c'est pas bon !

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Bonjour,

    Je reviens vers vous car je ne m'en sort pas !
    Je récupère dans ma méthodes la racine de la partition à copier (C:\ par exemple), sous forme de string.

    Et là ça se complique, quoi que je fasse, ca ne fonctionne pas.
    En fait, je n'arrive pas a manipuler ce fameux string. Sachant que pour que ca fonctionne, il semble que soit obligé d'avoir une variable déclarée de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    string source("C:\\*\0C:\\DEV\0\0", 13);
    je n'arrive pas à concaténer la racine, et le chemin du repertoire a copier.
    Quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    string source(src+"*\0"+src+DEV"\0\0", 13);
    Et enfin, si cette concaténation été possible, comment saurais-je la valeur de ma deuxième variable (13), qui représente le nombre de caractère de ma chaine ?

    Je suis paumé, c'est pourquoi je fait appel à vous.

    Cordialement,
    PKO
    Quand c'est trop, c'est pas bon !

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Essaie en passant par plusieurs std::string. Par contre, tu risques d'avoir un problème de caractère nul en les concaténant.
    Essaie peut-être un truc comme ça:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    string racinez("C:\\*\0", 5); //En théorie, cette string devrait avoir deux zéros terminaux. La concaténation en supprimera un.
    string dev = "C:\\DEV";
    string devz = dev + string("\0", 1); //Pareil
    string source = racinez+devz;
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Fais joujou en debug pas à pas avec ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    std::string s("\0a\0",3);
    cout << s.size() << endl;
    s.assign("\0b\0",3);
    cout << s.size() << endl;
    s.append("\0c\0",3);
    cout << s.size() << endl;
     
    #define STR_LEN(s) s,sizeof(s)-1
    std::string s(STR_LEN("\0a\0"));
    cout << s.size() << endl;
    s.assign(STR_LEN("\0b\0"));
    cout << s.size() << endl;
    s.append(STR_LEN("\0c\0"));
    cout << s.size() << endl;

  16. #16
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par Altess Voir le message
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    string source(src+"*\0"+src+DEV"\0\0", 13);
    Et enfin, si cette concaténation été possible, comment saurais-je la valeur de ma deuxième variable (13), qui représente le nombre de caractère de ma chaine ?
    Tu ne la connais pas. Donc concrêtement tu décomposes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    string source(src);
    source.append("*\0",2);
    source+=src;//pareil que source.append(src); et que source.append(src.c_str(),src.length());
    source.append("DEV\0\0",5);

  17. #17
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Bonjour Medinoc.

    Merci de ton aide. Ce que tu propose fonctionne, mais ca ne répond à mon problème. Mon objectif étant de rendre la lettre du lecteur variable. Je récupère cette dernière dans un string, que j'appelle "path". J'ai essayé ça, mais sans plus de réussite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    	string racinez(src,3); 
     
    	string dev = "DEV";
    	string devz = dev + string("\0", 1); //Pareil
     
    	string all = "*";
    	string allz = all + string("\0", 1);
     
    	string source = racinez+devz+allz;
    Sachant que src vaut : "C:\"

    Logiquement, un string c'est de la forme "aaa"
    Un string.c_str() c'est de la forme "aaa\0"

    Pourquoi est-ce si compliqué ? Et pourquoi un simple :
    lettre+path1.c_str()+path2.c_str()+...+'\0'
    ne fonctionne t'il pas ?
    Quand c'est trop, c'est pas bon !

  18. #18
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Parce que:
    • on ne peut pas additionner des pointeurs
    • Si tu ne précises pas la taille au constructeur de string, elle sera obligée de faire un strlen(). Contrairement à java, les chaines littérales ne stockent pas leur taille quelque part.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  19. #19
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    223
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 223
    Points : 193
    Points
    193
    Par défaut
    Bon, et bien merci à vous pour ces informations.
    Je me suis attentivement penché sur la taille des différents éléments qui composent cette chaine de caractère. Après bidouillage ici et là, j'ai réussi (grâce à vous) tant bien que mal a avoir un semblant de bon fonctionnement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	string src = "C";   // Ma variable
    	src+=":\\";
    	string lettre (src.c_str(),3);
     
    	lettre+="DEV"+string("\0",1);  // Mon chemin 1
    	lettre+=src;
    	lettre+="*"+string("\0\0",2);  // Mes fichiers
    Et je balance le tout dans la structure nécessaire a la méthode, sous cette forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    fop2.pFrom=lettre.c_str()
    Au final, ca fonctionne (enfin, je crois ... ).

    Je continu en faisant quelques tests. Si y'a du nouveau, je re-posterais.

    Merci à vous.
    Quand c'est trop, c'est pas bon !

  20. #20
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    J'ai l'impression d'avoir répondu pour rien, surtout quand je vois ce code cochonné...
    Citation Envoyé par Altess Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ...
     
    	lettre+="DEV"+string("\0",1);  // Mon chemin 1
     
    ...
    Tu peux pas utiliser append(), c'est si compliqué ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ...
     
    	lettre.append("DEV\0",4);  // Mon chemin 1
     
    ...
    D'une manière plus générale, tu peux concaténer toutes les chaines que tu veux sauf si elles contiennent des '\0'. Pour celles-ci tu dois explicitement les forcer en précisant la taille de la chaine (en faisant attention de ne pas se gourer, raison pour laquelle je proposais la macro STR_LEN())
    EDIT: bon, nos posts se sont croisés

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Copie Multiples en Lisp pour AutoCad
    Par grekenski108 dans le forum Lisp
    Réponses: 0
    Dernier message: 14/09/2012, 01h40
  2. Réponses: 8
    Dernier message: 26/09/2011, 14h44
  3. [XL-2003] Copie multiple d'une cellule
    Par demongin dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 24/06/2010, 13h55
  4. Copies multiples de données d'une base SQL à une autre
    Par leymiris dans le forum Langage SQL
    Réponses: 4
    Dernier message: 09/11/2008, 16h46
  5. Probleme de copie multiple
    Par blondelle dans le forum C++Builder
    Réponses: 12
    Dernier message: 11/09/2006, 16h50

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