ReadDirectoryChangesW blocks removal of a watched directory

I am trying to look at the directory for creating / deleting / renaming changes in Windows using python using the ReadDirectoryChangesW API. This is my code and it works fine:

results = win32file.ReadDirectoryChangesW(self.hDir, 8192, True, self.type, None, None) for action, file in results: full_filename = os.path.join (self.source_path, file) if action == 1: # Created self.fileCreated(full_filename) elif action == 2: # Deleted self.fileDeleted(full_filename) elif action == 3: # Updated self.fileUpdated(full_filename) elif action == 4: # Renamed from something renamed_file = full_filename elif action == 5: # Renamed to something self.fileRenamed(renamed_file, full_filename) 

However, when I try to delete the viewed folder from python or from a Windows browser, I get:

WindowsError: [Error 32] The process cannot access the file because it is being used by another process: 'c: \ users \ user \ appdata \ local \ temp \ new_dir'

I think it makes sense, but how do I solve it? Since my application should allow the user to delete the folder being viewed. I tried the solution for the asynchronous method http://www.themacaque.com/?p=859 , but that did not help.

Thanks in advance!

+3
source share
3 answers

From this blog post :

Another potential error [ReadDirectoryChangesW] is that the directory itself is now "used" and therefore cannot be deleted. To control the files in the directory and still allow the directory to be deleted, you will need to control the parent directory and its children.

The post also contains more information on the proper use of ReadDirectoryChangesW

+3
source

Removing IS watched folder is possible in ReadDirectoryChangesW

"Understanding ReadDirectoryChangesW - Part 2" by Jim Beveridge (as Artemug mentioned) is a very good background for this problem, but the expression explaining Using FILE_SHARE_DELETE is misleading.

My tests, using FILE_SHARE_DELETE actually allows you to delete / rename the viewed folder. (In other words, you do not need to โ€œwatch the parent folderโ€ as the only option.)

Here's a working snippet (edited and heavily borrowed from this excellent Tim Watch Gold Change Catalog)

 # License is same as snippets on this page # http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html # In other words, bug Tim Golden to publish a license for his snippets def windows_watch_path(watched_path): import win32file import win32con ACTIONS = { 1 : "Created", 2 : "Deleted", 3 : "Updated", 4 : "RenamedFrom", 5 : "RenamedTo" } # Thanks to Claudio Grondi for the correct set of numbers FILE_LIST_DIRECTORY = 0x0001 try: hDir = win32file.CreateFile ( watched_path , FILE_LIST_DIRECTORY , win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE , None , win32con.OPEN_EXISTING , win32con.FILE_FLAG_BACKUP_SEMANTICS , None ) except: # either it does not exist by this time, or some other issue... blah. # we'll just say "it 'changed' from 'some other expected state'" return [[watched_path, '', ACTIONS[2]]] results = win32file.ReadDirectoryChangesW ( hDir, 1024, True, 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, None, None ) files_changed = [] for action, fn in results: files_changed.append( [ watched_path , fn , ACTIONS[action] ] ) # print fullfn, ACTIONS.get(action, "Unknown") return files_changed 
+1
source

Well, this is not easy to solve ... In my case (http://www.themacaque.com/?p=859) I ignored the fact of allowing the directory to be renamed or deleted.

What you can do to allow the user to rename the clock folder is to use ReadDirectoryChangesW for the path's ancestor to view and filter events according to the tracks you are viewing. I have implemented a new way of doing a view using twisting to do event processing. With this solution, you could foresee ancestors if:

  • There are not too many brothers in the folder to ignore. You do not want to perform many and many operations to filter events that do not interest you.
  • No problem if the user cannot delete the ancestor.

In the Ubuntu One code on the windows, we are dealing with this problem, and we have implemented a good solution that you can take a look at. This is a bit related to the implementation of pyinotify on linux with a processor that will allow you to connect an object with callbacks that will be called according to the event in the main loop of twisted reactors. Take a look at this code, this may help you.

Any problem that I know about in my blog or in irc (in freenode on #ubuntuone or #pyar) my nickname is mandel;)

0
source

All Articles