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 :

Problème avec ReadDirectoryChangesW


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 61
    Par défaut Problème avec ReadDirectoryChangesW
    bonjour,

    J'ai un problème avec ReadDirectoryChangesW. Je cherche à surveiller un répertoire et faire une action lorsque des fichiers sont ajoutés dans ce répertoire (par un autre processus que je ne contrôle pas).

    Avec ReadDirectoryChangesW je détecte bien la création d'un fichier mais je souhaite en plus détecter la fin de création de ce fichier. Ces fichiers que je souhaite manipuler font parfois plusieurs Go or ça prend du temps pour se copier ce qui me cause quelques soucis

    Avec ReadDirectoryChangesW existe t il un moyen de ne déclencher l'événement FILE_ACTION_ADDED que lorsque le fichier est fini de copier?

    Merci d'avance pour votre aide.

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Nico118 Voir le message
    Avec ReadDirectoryChangesW existe t il un moyen de ne déclencher l'événement FILE_ACTION_ADDED que lorsque le fichier est fini de copier?
    Pas que je sache. Ceci dit, comment-est ce que tu défini "fini de copier" ?
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Je réfléchis de façon abstraite car je ne connais pas la(les) API(s) concernées, mais Nico118 ne pourrait-il pas utiliser son évènement pour ajouter le fichier à une liste de fichiers en cours d'écriture, et surveiller régulièrement pour voir quand le fichier est fermé en écriture? A moins que le process qui ajoute les fichiers ne fasse la copie en ouvrant le fichier en mode ajout plusieurs fois de suite, ne peut-il pas détecter le fait que le fichier est ouvert en écriture, et définir la fin de copie comme le moment où le fichier est refermé par le process qui fait la copie?

  4. #4
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 61
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Pas que je sache. Ceci dit, comment-est ce que tu défini "fini de copier" ?
    Quand je dit fini de copier pour moi ça veut dire que tous les octets du fichiers sont copiés

  5. #5
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Nico118 Voir le message
    Quand je dit fini de copier pour moi ça veut dire que tous les octets du fichiers sont copiés
    Oui, mais pour l'ordinateur, ça n'a aucun sens. Pour lui, il s'agit d'un ensemble d'écriture dans le fichier. Il peut détecter la création du fichier, ou une modification de sa taille, mais il ne pourras jamais te dire "ca y est, il a fini de grossir". Ne sachant pas que le fichier est généré lors d'une copie, il n'a aucune information sur laquelle il pourrait se baser.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  6. #6
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Il peut détecter la création du fichier, ou une modification de sa taille, mais il ne pourras jamais te dire "ca y est, il a fini de grossir".
    Donc, sais-tu si des API existent permettant de détecter que le fichier est actuellement ouvert en écriture par un process quelconque? Si le process qui copie le fichier fait son écriture en une fois (ouvre en écriture, balance toutes les données, j'ai finit, ferme le fichier), on pourrait déduire que la copie est finie du fait que le fichier est fermé en écriture. Est-ce que ça tient assez la route pour résoudre le problème de Nico118?

  7. #7
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 61
    Par défaut
    Citation Envoyé par therwald Voir le message
    Donc, sais-tu si des API existent permettant de détecter que le fichier est actuellement ouvert en écriture par un process quelconque? Si le process qui copie le fichier fait son écriture en une fois (ouvre en écriture, balance toutes les données, j'ai finit, ferme le fichier), on pourrait déduire que la copie est finie du fait que le fichier est fermé en écriture. Est-ce que ça tient assez la route pour résoudre le problème de Nico118?
    J'ai pensé à ça mais je n'ai pas réussi à le faire

  8. #8
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Pourrais-tu détailler les raisons de ton échec?
    est-ce que:
    • tu n'as pas trouvé d'API pour faire ça
    • ça se déclenche en cours de copie (ton process copieur ferme et réouvre le fichier plusieurs fois au cours de la copie)
    • autre chose?

  9. #9
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 61
    Par défaut
    Le process copieur (que je ne maitrise pas) copie le fichier d'un seul coup (c'est à dire que pour ce process le fichier est déjà complet lorsqu'il commence sa copie, il n'a pas de modification à faire sur ce fichier). La copie du fichier par l'autre process met un certain temps (le fichier peut faire plusieurs Go et la copie se fait au travers un réseau local), j'utilise ReadDirectoryChangesW pour surveiller le répertoire où sont copiés ces fichiers et mon problème c'est que ça me détecter qu'un fichier arrive, pas qu'un fichier est arrivé.

  10. #10
    Membre Expert
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Citation Envoyé par Nico118 Voir le message
    Le process copieur (que je ne maitrise pas) copie le fichier d'un seul coup (c'est à dire que pour ce process le fichier est déjà complet lorsqu'il commence sa copie, il n'a pas de modification à faire sur ce fichier). La copie du fichier par l'autre process met un certain temps (le fichier peut faire plusieurs Go et la copie se fait au travers un réseau local), j'utilise ReadDirectoryChangesW pour surveiller le répertoire où sont copiés ces fichiers et mon problème c'est que ça me détecter qu'un fichier arrive, pas qu'un fichier est arrivé.
    Soyons bien clairs: combien de processus y-a-t'il?
    Je croyais qu'il y en avait deux:
    • un processus copieur (disons p1) (crée les fichiers, met un certain temps car il ramène plusieurs Go)
    • ton processus (disons p2) (surveille pour faire une opération X sur les nouveaux fichiers)

    Est-ce que c'est bien ça?

    Si oui, la question est: comment fait p1? Est-ce qu'il ouvre le ficher en écriture et la garde ouvert tout le temps jusqu'à fin du transfert? Ou est-ce qu'il écrit les données par paquets d'un certaine taille en REFERMANT le fichier entre ses écritures?
    Si c'est le premier cas (une seule grande écriture, le fichier reste ouvert en écriture tant que la copie du fichier n'est pas finie) alors on pourrait une fois qu'on a listé le fichier comme ajouté par l'évènement sonder à intervalles réguliers jusqu'à ce qu'il soit fermé. Là on peut le traiter, car on sait que la copie est terminée. Si c'est le second cas (le processus p1 ferme puis ré-ouvre le fichier plusieurs fois au cours du processus de copie au fur et à mesure qu'il reçoit les données à travers le réseau) alors on ne peut pas s'en tirer par la détection de la fermeture du fichier, puisqu'il est plusieurs fois fermé et ré-ouvert avant la vraie fin de la copie.

    Sinon, lorsque tu dis que tu n'a pas de contrôle sur p1, veux tu dire que c'est un processus séparé ou que tu ne peux rien faire modifier dessus? Parce que si tu pouvais le faire modifier, tu pourrais faire en sorte qu'il fasse le transfert sur un autre répertoire DE LA MÊME PARTITION, puis qu'il déplace le fichier entier vers le répertoire que tu surveille. Comme ça vu que les données sont déjà là et qu'on ne fait que mettre à jour un lien, le fichier apparaîtrait dans le répertoire surveillé "d'un seul coup" (en fait en un temps très bref). Et ça devrait résoudre ton problème.

  11. #11
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 527
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 527
    Par défaut
    Citation Envoyé par Nico118 Voir le message
    mais je souhaite en plus détecter la fin de création de ce fichier. .
    Est-ce que tu utilises des EVENT ?
    Il faut créer un EVENT et appeler WaitForSingleObject.
    D'après les explications données ce ne semble pas le cas

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    Tu as tout un exemple détaillé ici
    http://msdn.microsoft.com/en-us/libr...(v=VS.85).aspx

  12. #12
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 61
    Par défaut
    Mon code ressemble à ça :
    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
    while(1) {
    	hDir = CreateFile(
    		Rep_FromAutomate,
    		FILE_LIST_DIRECTORY,
    		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    		NULL,
    		OPEN_EXISTING,
    		FILE_FLAG_BACKUP_SEMANTICS,
    		NULL);
     	bResult = ReadDirectoryChangesW(
    		hDir,
    		Buf,
    		10000,
    		FALSE,
    		FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_ACCESS,
    		&RetBytes,
    		NULL,
    		NULL);
     
    	for(;;) {
     
    	pInfo = (FILE_NOTIFY_INFORMATION *)&Buf[dwi];
    switch(pInfo->Action) {
    	case FILE_ACTION_ADDED:
    break;
    case FILE_ACTION_REMOVED:
    	printf("fichier supprime : %s\n", sNomFichier);break;
    default: 
    	printf("autre action sur le répertoire\n");
    	break;
    }
    };
     
    CloseHandle(hDir);

  13. #13
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par therwald Voir le message
    Donc, sais-tu si des API existent permettant de détecter que le fichier est actuellement ouvert en écriture par un process quelconque? Si le process qui copie le fichier fait son écriture en une fois (ouvre en écriture, balance toutes les données, j'ai finit, ferme le fichier), on pourrait déduire que la copie est finie du fait que le fichier est fermé en écriture. Est-ce que ça tient assez la route pour résoudre le problème de Nico118?
    Oui, mais qui te dis que le fichier sera ouvert et copié en une fois ? A moins d'avoir une contrôle quasi total le logiciel qui fait la copie, tu ne peux pas en être sûr. D'autant plus qu'un utilisateur peut avoir installé un hook sur CopyFile et CopyFileEx (par exemple pour utiliser Teracopy).

    Donc, en théorie, ça peut aider si c'est effectivement ce qui se passe, mais en pratique, un tel comportement ne peut pas être garanti.

    Pour déterminer si un fichier est ouvert en écriture par quelqu'un d'autre, il suffit de vérifier s'il est ouvrable de manière exclusive. S'il ne l'est pas, mais qu'il existe, alors le fichier est en cours d'utilisation. Donc : OpenFile() avec OF_SHARE_EXCLUSIVE comme flag.

    OF_SHARE_EXCLUSIVE (0x00000010)
    Opens a file with exclusive mode, and denies both read/write access to other processes. If a file has been opened in any other mode for read/write access, even by the current process, the function fails.
    cf. http://msdn.microsoft.com/en-us/libr...(v=VS.85).aspx
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  14. #14
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 61
    Par défaut
    Merci pour toutes vos réponses.

    Donc il faudrait que je code quelque chose du genre ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while(OpenFile(lpFileName, lpReOpenBuff, OF_SHARE_EXCLUSIVE))
    {
    }
    Si mon fichier met plusieurs minutes pour être fini de copier, je suis aveugle pendant ce temps non?

  15. #15
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    do {
      // pas DENY_WRITE, mais bien EXCLUSIVE. Les deux valeurs n'ont pas du tout la 
      // même sémantique, et c'est la sémantique de EXCLUSIVE que tu cherches
      // a obtenir.  
      HFILE f = OpenFile(lpFileName, lpReOpenBuff, OF_SHARE_EXCLUSIVE);
      if (f != HFILE_ERROR) {
        // si on a réussi à ouvrir le fichier, on est bon. 
        CloseHandle(f);
        break;
      }
      Sleep(0); // au moins ; Un sleep plus important ne serait pas plus mal ; voir ce que tu peut mettre ici (50 ? 100 ? 250 me semble être pas mal). 
    }
    //SetEvent(hEventFileOk);
    Dans l'idéal, ce code est placé dans un thread, et ce thread fait un SetEvent() une fois que le fichier est considéré comme OK.

    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
     
    struct filecheckinfo
    {
      std::string filename;
    };
     
    DWORD WINAPI my_thread_func(LPVOID param)
    {
      filecheckinfo* fci = reinterpret_cast<filecheckinfo*>(param);
      if (!fci)
        return (DWORD)(-1);
      do {
        // pas DENY_WRITE, mais bien EXCLUSIVE. Les deux valeurs n'ont pas du tout la 
        // même sémantique, et c'est la sémantique de EXCLUSIVE que tu cherches
        // a obtenir.  
        OFSTRUCT reopenbuf;
        HFILE f = OpenFileA(fci->filename.c_str(), &reopenbuf, OF_SHARE_EXCLUSIVE);
        if (f != HFILE_ERROR) {
          // si on a réussi à ouvrir le fichier, on est bon. 
          CloseHandle(f);
          break;
        }
        Sleep(250);
      }
      return 0;
    }
     
    // A appeler dans le thread d'attente du fichier. 
    // a noter que le WaitForSingleObject peut prendre une paramètre de timeout qui n'est pas
    // INFINITE, ce qui va le faire échouer régulièrement sur une erreur WAIT_TIMEOUT. 
    // Du coup, un autre traitement est possible toutes les X millisecondes si besoin. 
    DWORD do_check(const std::string filename)
    {
      filecheckinfo fci; 
      DWORD result;
     
      HANDLE hthread = CreateThread(NULL, 0, my_thread_func, (LPVOID)(&fci), 0, NULL);
      if (hthread == INVALID_HANDLE_VALUE)
        return (DWORD)(-1);
     
      WaitForSingleObject(hthread, INFINITE);
     
      GetExitCodeThread(hthread, &result);
      return result;
    }
    Ceci dit, effectivement, tant que le fichier n'est pas accessible, tu ne peux pas faire grand chose. C'est à toi de trouver la parade.

    A noter aussi que tu peux avoir plusieurs threads en parallèle qui vérifie si un fichier parmi plusieurs est dispo (grâce à WaitForMultipleObjects).

    Enfin bon, après, c'est toi qui voit
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  16. #16
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2002
    Messages
    61
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 61
    Par défaut
    Ce code me lève une exception :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    do
    {
    res = OpenFile(new_fichier.c_str(), reopenbuf, OF_SHARE_EXCLUSIVE);
    if (res != HFILE_ERROR) {
    // si on a réussi à ouvrir le fichier, on est bon. 
    CloseHandle((HANDLE)res);
    break;
    }
    Sleep(50);
    }
    while(1);
    Une exception non gérée du type 'System.AccessViolationException' s'est produite dans Test.exe

    Informations supplémentaires*: Tentative de lecture ou d'écriture de mémoire protégée. Cela indique souvent qu'une autre mémoire est endommagée.
    Note qu'en remplaçant OF_SHARE_EXCLUSIVE par OF_READ je n'ai pas d'exception mais res (le HFILE) vaut toujours -1 donc je reste bloqué dans ma boucle même après la fin de la copie du fichier.

    Pour mes tests, le second process (celui qui copie les gros fichiers dans mon répertoire) est simulé par un copier coller depuis l'explorateur Windows 7.

Discussions similaires

  1. Réponses: 0
    Dernier message: 19/12/2007, 20h17
  2. VC++ Direct3D8, problème avec LPD3DXFONT et LPD3DTEXTURE8
    Par Magus (Dave) dans le forum DirectX
    Réponses: 3
    Dernier message: 03/08/2002, 11h10
  3. Problème avec le type 'Corba::Any_out'
    Par Steven dans le forum CORBA
    Réponses: 2
    Dernier message: 14/07/2002, 18h48
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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