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

Windows Discussion :

[Win Api32] [C] Problème de copie de fichiers


Sujet :

Windows

  1. #1
    Membre régulier Avatar de acryline
    Profil pro
    Inscrit en
    Août 2006
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 200
    Points : 101
    Points
    101
    Par défaut [Win Api32] [C] Problème de copie de fichiers
    Bonjour, un autre sujet a été ouvert sur le même thème ici (un peut plus bas dans ce forum) mais comme il est "Résolu" 'j'ai préféré en ouvrir un second.

    J'ai toujours le même problème, mon application plante au moment où j'essaie de définir les répertoires de sauvegarde et de récupération des dossiers que j'aimerais copier.

    J'ai corrigé mon code et maintenant j'utilise des TCHAR et les fonctions qui vont avec.
    Le programme plante éxactement à la première ligne de la fonction definirAdresseOrigine. J'ai recopié celle de Médinoc. J'ai bien fait l'allocation dynamique où il me conseille de la faire et je libère la mémoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    LPTSTR definirAdresseOrigine(LPCTSTR dossier, LPCTSTR user)
    {
    	LPTSTR adresseFrom = NULL;
     
    	/* Calculer la longueur de chaîne à allouer, 
    	   caractère nul supplémentaire compris. */
    	size_t cchLength = _stprintf(_T("C:\\DOCUME~1\\%s\\%s\\*%c"), user, dossier, _T('\0'));
    J'ai seulement changé sctprintf par stprintf je ne trouvais pas la première fonction et j'ai pensé que c'était une faute de frappe...Mais avec une addition de strlen ça plante quand même.

    Comme j'utilise Codeblocks j'ai débugger mon code. Et a cette ligne j'option une erreur et voici le log

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #0 77C0EFF9	wscanf() (C:\WINDOWS\system32\msvcrt.dll:??)
    
    #1 77C0F296	wscanf() (C:\WINDOWS\system32\msvcrt.dll:??)
    
    #2 0022FC10	??() (??:??)
    
    #3 00405266	??() (??:??)
    
    #4 00000000	??() (??:??)
    Ensuite le programme s'arrête.

    Une autre info, comme je l'avais dit dans mon premier sujet, je remplis la structure SHFILEOPSTRUCTURE :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct _SHFILEOPSTRUCT {
        HWND hwnd;
        UINT wFunc;
        LPCTSTR pFrom;
        LPCTSTR pTo;
        FILEOP_FLAGS fFlags;
        BOOL fAnyOperationsAborted;
        LPVOID hNameMappings;
        LPCTSTR lpszProgressTitle;
    } SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;

    Voici la doc de la Structure


    Si qq'un pouvait m'aider à trouver ce qui ne va pas ça serait sympa, j'ai l'impression de tourner en rond. Merci !

  2. #2
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Ça marche pas comme ça sprintf, elle prend un buffer en premier paramètre.
    Ajouter à la main le zéro terminal était une bonne intention mais ce n'est pas utile, une chaine littérale en contient déjà un.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TCHAR buffer[une certaine taille];
    size_t cchLength = _stprintf(buffer, _T("C:\\DOCUME~1\\%s\\%s\\*"), user, dossier);
    Mais ce n'est pas du C++ pur et c'est dangereux parce qu'on utilise un buffer à taille fixe, en C++ on pourrait faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    std::string buffer = _T("C:\\DOCUME~1\\");
    buffer += user;
    buffer += _T("\\");
    buffer += dossier;
    buffer += _T("\\*");
    
    size_t cchLength = buffer.size();
    Et c'est toujours pas bien parce que le répertoire utilisateur est pas forcément dans "c:\Documents and Settings", le mieux c'est de lire la variable d'environement USERPROFILE ou SHGetFolderPath

  3. #3
    Membre régulier Avatar de acryline
    Profil pro
    Inscrit en
    Août 2006
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 200
    Points : 101
    Points
    101
    Par défaut
    et qu'est ce qui est bien ? (à part Linux et GTK+ )

    Pour le caractère nul supplémentaire il est là à cause le la structure :
    Each file name must be terminated by a single NULL character. An additional NULL character must be appended to the end of the final name to indicate the end of pFrom.
    Pour la fonction SHGetFolderPath

    Deprecated. Gets the path of a folder identified by a CSIDL value.
    Un peu d'aide SVP ?

  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
    Tu as mal recopié mon code: Le premier appel n'est pas à _stprintf(), mais à _sctprintf()...

    Mais maintenant, tu peux utiliser cette version-là à la place de toute façon.
    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 régulier Avatar de acryline
    Profil pro
    Inscrit en
    Août 2006
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 200
    Points : 101
    Points
    101
    Par défaut
    Oui j'ai essayé cette fonction mais j'obtiens tjrs :
    undefined reference to '__sctprintf'
    et je ne la trouve pas pour vérifier à quelle bibliothèque elle appartient ... elle est référencée une fois je crois dans le site de windows et seulement mentionnée.. ou je cherche très mal.

  6. #6
    Membre régulier Avatar de acryline
    Profil pro
    Inscrit en
    Août 2006
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 200
    Points : 101
    Points
    101
    Par défaut
    Bon j'ai cru que ma version de XP était trop vieille (j'ai un viel XP sur une machine virtuelle) Mais la fonction n'est toujours pas reconnue sur mon portable avec Vista.
    J'ai vu des sources de tchar.h sur internet, et pas de _sctprintf ...
    Un vrai casse tête, c'est un jeu de piste ?

    J'ai réinstallé code::blocks, je pense que le bug vient de laà, maisil ne veut plus compiler... trop chaud, fatigue... je verrai ça demain.

  7. #7
    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
    _sctprintf() est supposé être un #define sur _scprintf() ou _scwprintf().
    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.

  8. #8
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par acryline
    Bon j'ai cru que ma version de XP était trop vieille (j'ai un viel XP sur une machine virtuelle) Mais la fonction n'est toujours pas reconnue sur mon portable avec Vista.
    D'ailleurs le système utilisé n'a rien à voir dans le processus de compilation, c'est l'environnement de développement qu'il faut changer si tu veux changer quelque chose ...

    Citation Envoyé par Twindruff
    Mais ce n'est pas du C++ pur ..., en C++ on pourrait faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    std::string buffer = _T("C:\\DOCUME~1\\");
    buffer += user;
    buffer += _T("\\");
    buffer += dossier;
    buffer += _T("\\*");
    
    size_t cchLength = buffer.size();
    Et ça ce n'est pas du Windows pur . En plus, utiliser _T() avec des std::string (std::basic_string<CHAR>) ... huh ! En Windows on peut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <windows.h>
    #include <strsafe.h>
    
    #define BUFLENGTH(t) (sizeof(t) / sizeof(t[0]))
    
    TCHAR lpszBuffer[MAX_PATH];
    
    StringCchPrintf(lpszBuffer, BUFLENGTH(lpszBuffer), TEXT("C:\\DOCUME~1\\%s\\%s\\*"), user, dossier);

  9. #9
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Citation Envoyé par Melem Voir le message
    Et ça ce n'est pas du Windows pur .
    Ah oui j'ai cru que j'étais dans le forum C++ Dans ce cas là ouais vaut mieux utiliser les trucs de l'api.

    Citation Envoyé par Melem Voir le message
    En plus utiliser _T() avec des std::string (std::basic_string<CHAR>) ... huh ! En Windows on peut faire :
    std::basic_string<TCHAR> était sous entendu

  10. #10
    Membre régulier Avatar de acryline
    Profil pro
    Inscrit en
    Août 2006
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 200
    Points : 101
    Points
    101
    Par défaut
    J'ai réinstallé code blocks correctement, _sctprintf() n'est tjrs pas réconnue.

    D'ailleurs le système utilisé n'a rien à voir dans le processus de compilation, c'est l'environnement de développement qu'il faut changer si tu veux changer quelque chose ...
    je dirais même plus, un peu avant j'avais posté ça
    J'ai réinstallé code::blocks, je pense que le bug vient de laà, maisil ne veut plus compiler... trop chaud, fatigue... je verrai ça demain.
    _sctprintf() est supposé être un #define sur _scprintf() ou _scwprintf().
    Et à part ça je fais quoi ? ça a tellement l'air d'être simple pour certains, ...en apparence, mais pour l'instant aucune solution claire et nette, on se demande si qq fois ce forum n'est pas plus un faire valoir qu'un endroit où trouver de l'aide.

    Si vraiment le but était d'aider il y a longtemps que j'aurais ma réponse... un exemple hier soir j'ai aidé qq'un qui ne savait pas du tout comment faire pour installer une standalone d'opensim, installation de base de données, du logiciel de l'hypergrid, configuration... maintenant cette personne a une standalone fonctionnelle.
    Ok vous n'êtes pas obligés d'aider mais vous n'êtes pas non plus obligés de donner des réponses floues, avec des erreurs (4 au moins dans un code là pour aider c'est quand même un comble...) et qq fois désagréables qui font plutot reculer les choses.Apparemment vous n'aidez que ceux qui savent déjà.Etrange.

    Bon sur ce je pense que je n'ai plus à attendre d'aide de votre part ...pas grave, ça fait du bien. ?Nombreux sont les gens qui ne demandent pas d'aide de peur de tomber entre vos mains.
    Je parle pour eux.

  11. #11
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Et la fonction StringCchPrintf alors ? Je ne connais pas de meilleur remplacement pour les fonctions de la famille sprintf. J'ai donné un exemple d'utilisation plus haut mais il faut en plus se lier avec strsafe.lib. C'est une fonction Win32 donc t'auras aucun problème quel que soit le compilateur que tu utilises (C::B, Visual, Borland, etc.).

  12. #12
    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 rajoutant ce bout de code dans un fichier d'en-tête ou en haut de ton fichier source:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #ifndef _sctprintf
    #ifdef _UNICODE
    #define _sctprintf _scwprintf
    #else
    #define _sctprintf _scprintf
    #endif
    #endif

    Edit: @Melem: StringCchPrintf() ne permet pas de calculer la taille requise avant allocation (ce à quoi servent _scprintf() et snprintf()).
    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.

  13. #13
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Oui, mais au moins on a argument qui spécifie la taille du buffer destination que sprintf n'a pas et une fonction garantie dispo sur toutes les versions supérieures ou égales à 32 bits de Windows et qui n'est pas marquée deprecated par les dernières versions de Visual. Juste une petite comparaison :

    sprintf :
    + : C90 donc très portable
    - : Pas d'argument qui permet de spécifier la taille du buffer destination

    snprintf :
    + : Possède argument qui permet de spécifier la taille du buffer destination
    + : Permet de connaître la taille requise pour stocker une chaîne formatée avant de réserver de la mémoire pour la chaîne.
    - : C99 donc peu supporté par les compilateurs actuels dont Visual C++.

    _snprintf (et _scprintf) :
    + : Utilisée avec _scprintf, permet de fabriquer facilement une fonction identique à snprintf.
    - : Spécique Visual C++ (mais éventuellement supportée par d'autres compilateurs).
    - : N'ajoute pas le caractère nul terminal si le buffer est plein.
    - : _snprintf est marquée deprecated depuis Visual 2005.

    StringCchPrintf :
    + : Fonction de l'API Windows donc dispo partout où l'API Win32 est supportée.
    + : Possède argument qui permet de spécifier la taille du buffer destination
    + : Pas marquée deprecated par Visual.
    - : Ne permet pas de connaître a taille requise pour stocker une chaîne formatée avant de réserver de la mémoire pour la chaîne (donc c'est juste du _snprintf, sans _scprintf).

    Mais c'est vrai que l'argument buf_length en fait n'est pas si important que ça du moment qu'on utilise bien la fonction. C'est un peu comme strcpy. C'est réellement la fonction _scprintf ou équivalente, que l'API Win32 (si on exclut MSCVCRT) n'a pas, qui est importante car elle permet de réserver la taille juste requise pour stocker une chaîne formatée.

  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
    Tu peux rajouter cette ligne à _snprintf() :
    - N'ajoute pas le caractère nul terminal si le buffer est plein.
    Une fonction que j'aimais bien sur certaines plate-formes, mais qui n'a jamais intégré aucun standard (pas même POSIX), c'était asprintf() : le "a" signifiant "allocate"...
    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 actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Sinon comme je disais plus haut vaut mieux utiliser SHGetFolderPath puisque le répertoire de l'utilisateur n'est pas forcément dans "c:\document and settings"
    Tu peux faire ça par exemple pour l'utilisateur courant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TCHAR buffer[MAX_PATH];
    SHGetFolderPathAndSubDir(NULL, CSIDL_PROFILE  | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, dossier, buffer);
    Après si tu veux récupérer le chemin pour les autres utilisateur il faut que tu ajuste le troisième paramètre (voir la doc).

    (Je préfère utiliser SHGetFolderPath à SHGetKnownFolderPath pour que ça marche sous xp.)

Discussions similaires

  1. Problème de copie de fichier sur serveur
    Par Vincinho dans le forum Servlets/JSP
    Réponses: 4
    Dernier message: 07/04/2009, 14h51
  2. Problème de copie de fichier par FTP
    Par tpdm dans le forum AS/400
    Réponses: 3
    Dernier message: 31/07/2008, 15h37
  3. C# problème de copie de fichiers.
    Par Shypster dans le forum C#
    Réponses: 9
    Dernier message: 25/01/2008, 16h46
  4. [Système] problème de copie de fichier entre 2 serveurs
    Par HOUDEBINE dans le forum Langage
    Réponses: 2
    Dernier message: 22/05/2006, 16h13
  5. problème de copie de fichier...
    Par Pe04 dans le forum Langage
    Réponses: 5
    Dernier message: 22/03/2006, 10h17

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