2013-01-05 4 views
3

J'ai essayé d'obtenir ReadDirectoryChangesW pour surveiller un sous-arbre pour les changements de fichiers, mais j'ai constaté que je reçois des résultats incohérents. Ce qui suit est un cas de test autonome qui illustre le problème. Quand je lance ce qu'il produit parfois:ReadDirectoryChangesW semble manquer des événements

A : Created 
C : Updated 
A : Deleted 

Une autre fois, il pourrait produire:

A : Created 
B : Updated 
C : Updated 
A : Deleted 

créer un tampon énorme, et le nombre de fichiers en cours de modification est très faible (3 fichiers).

Le code:

import os, sys, time, threading 
import win32file, win32event, win32con, pywintypes 

class ChangeFiles (threading.Thread) : 
    def run(self) : 
     files = [ 'A', 'B', 'C' ] 
     time.sleep(1) 
     for path in files : f = open(path, 'w'); f.write('mooo'); f.close() 
     time.sleep(0.5) 
     for path in files : os.remove(path) 

ChangeFiles().start() 

FILE_LIST_DIRECTORY = 0x0001 

handle = win32file.CreateFile (
    '.', 
    FILE_LIST_DIRECTORY, 
    win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE, 
    None, 
    win32con.OPEN_EXISTING, 
    win32con.FILE_FLAG_BACKUP_SEMANTICS | win32file.FILE_FLAG_OVERLAPPED, 
    None 
) 

buffer = win32file.AllocateReadBuffer(1024 * 64) 
overlapped = pywintypes.OVERLAPPED() 
overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None) 

readFlags = win32con.FILE_NOTIFY_CHANGE_FILE_NAME | \ 
      win32con.FILE_NOTIFY_CHANGE_DIR_NAME | \ 
      win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES | \ 
      win32con.FILE_NOTIFY_CHANGE_SIZE  | \ 
      win32con.FILE_NOTIFY_CHANGE_LAST_WRITE | \ 
      win32con.FILE_NOTIFY_CHANGE_SECURITY 

ACTIONS = { 1 : "Created", 2 : "Deleted", 3 : "Updated" } 

while 1 : 
    win32file.ReadDirectoryChangesW(handle, buffer, False, readFlags, overlapped) 

    rc = win32event.WaitForSingleObject(overlapped.hEvent, 200) 

    if rc == win32event.WAIT_OBJECT_0 : 
     nbytes = win32file.GetOverlappedResult(handle, overlapped, True) 
     if nbytes > 0 : 
      for action, file in win32file.FILE_NOTIFY_INFORMATION(buffer, nbytes) : 
       print '%s : %s' % (file, ACTIONS.get (action, "Unknown")) 
     else : 
      print 'no bytes' 
      break 
    elif rc < 0 : 
     print 'Error: %d' % win32api.GetLastError() 
     break 
+0

Je commence à deviner que c'est une situation où, si un arbre tombe dans la forêt et qu'il n'y a personne autour pour l'entendre, est-ce qu'il fait encore un bruit? Dans ce cas, s'il n'y a pas d'appel en attente à ReadDirectoryChangesW, et qu'une modification est apportée au système de fichiers, en apprendrez-vous plus long sur le changement? Peut-être pas. J'ai utilisé une bibliothèque python appelée watchdog qui semble fonctionner pour moi, mais j'aimerais quand même savoir pourquoi mon exemple de code ci-dessus manque des événements. –

+1

Selon la [documentation] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx), les modifications _Directory qui se produisent entre les appels à cette fonction sont ajoutés au tampon, puis renvoyés avec l'appel suivant. Les événements doivent donc être mis en mémoire tampon jusqu'à votre prochain appel. Je n'ai jamais utilisé python, mais je n'ai eu aucun problème avec cette API en code natif. – Luke

Répondre

0

Le problème ici est que le délai d'attente vous passez à WaitForSingleObject est très faible, de sorte que la fonction tend à expirer avant de vous informé sur les événements. Votre code ne vérifie pas cette condition, donc vous ne voyez aucune sortie (essayez aussi le rc > 0).

Vous pouvez résoudre ce problème en transmettant la valeur INFINITE (c'est-à-dire 0xFFFFFFFF) à WaitForObject.

Questions connexes