Page 1 of 1

Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Tue Aug 02, 2011 8:02 pm
by jpfiste
Hello,

in previous thread http://www.purebasic.fr/english/viewtop ... rychangesw I've postet a example for ReadDirectoryChangesW. Due to conflicts in a current project I changed the function call because my previous version didn't work well. Now here is the new code as a simple sample.

What does the code?
The code creates a thread that executes the ReadDirectoryChangesW synchronous for a non-blocking app. The main app is a simple window loop with a listbox that displays the changes. The observed dir is C:\Test (you can simply change it in the test code).

What was wrong with the previous version?
Simply all. The buffer (*lpBufer) must not declared as FILE_NOTIFY_INFORMATION. The Buffer should simple be a allocated pointer of the size <= 64K. When a change happens the ReadDirectoryChangesW return. The filled buffer is structured as FILE_NOTIFY_INFORMATION. One Entry - One Change.

Code: Select all

; Notify filter values
#FILE_NOTIFY_CHANGE_FILE_NAME = 1
#FILE_NOTIFY_CHANGE_DIR_NAME = 2
#FILE_NOTIFY_CHANGE_ATTRIBUTES = 4
#FILE_NOTIFY_CHANGE_SIZE = 8
#FILE_NOTIFY_CHANGE_LAST_WRITE = $10
#FILE_NOTIFY_CHANGE_LAST_ACCESS = $20
#FILE_NOTIFY_CHANGE_CREATION = $40
#FILE_NOTIFY_CHANGE_SECURITY = $100
#FILE_NOTIFY_CHANGE_ALL = $17F

; not defined in purebasic
#FILE_SHARE_DELETE = 4

; Notify events
Enumeration
  #FILE_ACTION_ADDED = 1
  #FILE_ACTION_REMOVED
  #FILE_ACTION_MODIFIED
  #FILE_ACTION_RENAMED_OLD_NAME
  #FILE_ACTION_RENAMED_NEW_NAME
EndEnumeration

; Needed for creating a watching thread
Structure WatchFSParam_t
  Directory.s
  Filter.l
EndStructure

; structure for the needed
Structure FILE_NOTIFY_INFORMATION
  NextEntryOffset.l
  Action.l
  FileNameLength.l
  Filename.s{512}
EndStructure

Import "kernel32.lib"
  ReadDirectoryChangesW(hDirectory.l, *lpBuffer, nbBufferLen.l, bWatchSubTree.b, dwNotifyFilter.l, *lpBytesReturned.l, *lpOverlapped.OVERLAPPED, lpCompletitionRoutine)
EndImport

Procedure WatchDirOrFile(*params.WatchFSParam_t)
  
  Protected *buffer = AllocateMemory(32*1024)
  Protected *ovlp.OVERLAPPED = AllocateMemory(SizeOf(OVERLAPPED))
  Protected dwOffset.l = 0
  Protected *pInfo.FILE_NOTIFY_INFORMATION
  
  hDir = CreateFile_(*params\Directory, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE | #FILE_SHARE_DELETE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
  
  While ReadDirectoryChangesW(hDir, *buffer, MemorySize(*buffer), #True, *params\Filter, bytesRead, *ovlp, #Null)
    
    dwOffset = 0
    
    Repeat
      
      *pInfo = *buffer + dwOffset
      
      filename$ = PeekS(@*pInfo\Filename, *pInfo\FileNameLength, #PB_Unicode)
      
      action$ = #NULL$

      Select *pInfo\Action
        Case #FILE_ACTION_ADDED
          action$ = "ADDED"
        Case #FILE_ACTION_MODIFIED
          action$ = "MODIFIED"
        Case #FILE_ACTION_REMOVED
          action$ = "REMOVED"
        Case #FILE_ACTION_RENAMED_NEW_NAME
          action$ = "RENAMED_NEWNAME"
        Case #FILE_ACTION_RENAMED_OLD_NAME
          action$ = "RENAMED_OLDNAME"
      EndSelect
      
      AddGadgetItem (0, -1, filename$ + " " + action$)
      
      dwOffset + *pInfo\NextEntryOffset
      
    Until *pInfo\NextEntryOffset = 0
    
  Wend
  
EndProcedure

Procedure.l WatchFileSystem(DirectoryName.s, NotifyFilter.l = #FILE_NOTIFY_CHANGE_FILE_NAME)
  
  *watcherparams.WatchFSParam_t = AllocateMemory(SizeOf(WatchFSParam_t))
  *watcherparams\Directory = DirectoryName
  *watcherparams\Filter = NotifyFilter
 
  CreateThread(@WatchDirOrFile(), *watcherparams)
  
EndProcedure



; USAGE
If OpenWindow(0, 0, 0, 320, 240, "FileSystemWatch", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ListViewGadget(0, 10, 10, 300, 200)

  WatchFileSystem("C:\Test")

  Repeat
    Event = WaitWindowEvent()
    Delay(5)
  Until Event = #PB_Event_CloseWindow
  
EndIf


Enjoy the code

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Tue Aug 02, 2011 8:20 pm
by Tenaja
Thanks for sharing! This is exactly what I was looking for in this post:
http://purebasic.fr/english/viewtopic.php?f=17&t=46986


Perhaps somebody more knowledgeable than I can answer this: after the program has run, and this program reports file deletions, why are they not in the (Win7) recycle bin? Is there any (simple) way to recover them?

Thanks again!

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Tue Aug 02, 2011 8:42 pm
by jpfiste
Nice, that the code could help you. But don't forget: It's a very basic example. No pointer will be cleared. This is necessary for a productive release because on more changes the reading can cause error due to offset problems. This example should only show the way how the function ReadDirectoryChanges should be used.

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Tue Aug 02, 2011 10:35 pm
by rsts
Tenaja wrote:after the program has run, and this program reports file deletions, why are they not in the (Win7) recycle bin? Is there any (simple) way to recover them?

Thanks again!
after the program has run - which program the one in this thread?
and this program reports file deletions - this program? Does not report deletions. Do you mean REMOVED?

cheers

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Wed Aug 03, 2011 1:10 am
by Tenaja
Yes, sorry, my English was not clear; I did not learn English until after I could walk, and it was my first language, so I was not so good at languages yet. :mrgreen:

How is this?
My goal is to view temporary files that a program uses. After my "watched" program has run, and jpfiste's program reports a file has been ADDED and then REMOVED, why are the REMOVED files not in the (Win7) recycle bin? Is there any (simple) way to recover them?


...apparently, I inferred that REMOVED meant deleted... is there a way to remove a file without deleting it?

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Wed Aug 03, 2011 5:51 am
by rsts
A file will be reported "REMOVED" if it's moved to another location, in which case it will not be in the recycle bin.

It is also possible to bypass the recycle bin on deletions, which would result in "REMOVED" with nothing in the recycle bin.

Are you experiencing a case where a file is being deleted (not simply removed) and should be in the recycle bin but is not?

cheers

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Wed Aug 03, 2011 8:48 am
by moogle
There's a little bug where filename$ contains the previous file characters instead of being reset.

ie if it says

"New folder1234" created

and the next action is creating a new folder called "Test"

it will display "Testfolder1234" as the "folder1234" part is still there and the "New " part has been overwritten.

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Wed Aug 03, 2011 9:33 am
by jpfiste
Ok.

The file is removed from the folder. It's only the change. Deleting and removing is for Readdirectorychanges the same if you have the filter FILE_NAME. You can also play a little with the filters.

Of course there is a bug with reading multiple changes. As I said - it's a minimal example that should demonstrate how the call of ReadDirectoryChangesW should be done. To fix the bug *lpBuffer after the Repeat-Loop (And Allocate it new) and Clear the *pInfo. Then the filename changes are correct.

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Fri Sep 09, 2011 11:58 pm
by Thunder93
Thanks jpfiste!

Experienced the following;

Manually delete: Text Document - Copy - Copy.txt
FileSystemWatch: New Text Document - Copy - Copy.txt REMOVED

Manually Delete: Text Document.txt
FileSystemWatch: New Text Document.txtopy - Copy.txt REMOVED


Edited: Please visit http://www.purebasic.fr/english/viewtop ... 13&t=54038 for the fix.

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Sat Sep 10, 2011 6:01 am
by Thunder93
My change to address the incorrect filenames length worked good for single file changes but there’s still problem under simultaneous file changes...

I gave up on that code, Sparkie 2005 works good - http://www.purebasic.fr/english/viewtop ... c&start=17

Re: Monitor FileSystem Changes ReadDirectoryChangesW

Posted: Thu Sep 22, 2011 8:08 pm
by jassing
jpfiste wrote:This example should only show the way how the function ReadDirectoryChanges should be used.
Is there a better, more complete, example?