Anwendung ReadDirectoryChangesW

Share your advanced PureBasic knowledge/code with the community.
jpfiste
User
User
Posts: 18
Joined: Thu Feb 18, 2010 10:05 pm

Anwendung ReadDirectoryChangesW

Post by jpfiste »

Hello,

sorry for that mistake. I've forget in which forum I am. :D

And sorry for my bad following english.

The following code can be used to get notification on changes in a directory. In contrast to the FindFirstChangeNotification function I used ReadDirectoryChangesW. This has the benefit, that I can get the name of the changed element.

:arrow: Attention:Please set under compiler settings "Create unicode executable". Without that setting the filename isn't displayed correctly.

Ok, let us begin with a few definitions. The following constants are for building the filter setting for the function. With the filter you can define the behaviour of your notification.

Code: Select all

; dwNotifyFilter 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
This constant is also useful. It is often used in combination with the CreateFile function (that we need later).

Code: Select all

#FILE_SHARE_DELETE = 4
With the ReadDirectoryChangesW you can request the action that happed to the given item. The following enum gives you the existing actions that can occure.

Code: Select all

Enumeration
  #FILE_ACTION_ADDED = 1
  #FILE_ACTION_REMOVED
  #FILE_ACTION_MODIFIED
  #FILE_ACTION_RENAMED_OLD_NAME
  #FILE_ACTION_RENAMED_NEW_NAME
EndEnumeration
At next we need a Structure the ReadDirectoryChanges function can fill with information. After calling the function you can retrieve the filename from the structure and the actions that has taken place. The FieldNameLenght gives you the length for Unicode (5 letters -> FilenameLength=10)

Code: Select all

; Notify info structure
Structure FILE_NOTIFY_INFORMATION
  NextEntryOffset.l
  Action.l
  FileNameLength.l
  Filename.s{255}
EndStructure
The ReadDirectoryChangesW function is not defined in PureBasic (or I didn't found it). The workaround is a prototype. I also define a variable with the type of the defined prototype (for later use).

Code: Select all

Prototype.b _ReadDirectoryChangesW(hDirectory.l, *lpBuffer,nBufferLength.l,bWatchSubtree.b,dwNotifyFilter.l,*lpBytesReturned,*lpOverlapped.OVERLAPPED,lpCompletionRoutine)
Define ReadDirectoryChangesW._ReadDirectoryChangesW
Ok, definitions are made. Now let us come to the function that you can use or customize (for productive use).

Code: Select all

Procedure WatchDirOrFile(name$, filter.l = #FILE_NOTIFY_CHANGE_CREATION|#FILE_NOTIFY_CHANGE_LAST_ACCESS|#FILE_NOTIFY_CHANGE_DIR_NAME)
  Shared ReadDirectoryChangesW
  
  ; allocate buffer for results
  Define *buffer.FILE_NOTIFY_INFORMATION = AllocateMemory(SizeOf(FILE_NOTIFY_INFORMATION))
  Define ovlp.OVERLAPPED
  Define ReadDirectoryChangesW._ReadDirectoryChangesW  
  
  If Not ReadDirectoryChangesW
    *kernel32dll = OpenLibrary(#PB_Any,"kernel32.dll")
    ReadDirectoryChangesW = GetFunction(*kernel32dll,"ReadDirectoryChangesW")
  EndIf

    
  ; get handle to directory
  hDir = CreateFile_(name$,#FILE_LIST_DIRECTORY,#FILE_SHARE_READ|#FILE_SHARE_WRITE|#FILE_SHARE_DELETE,#Null,#OPEN_EXISTING,#FILE_FLAG_BACKUP_SEMANTICS,#Null)
  
  While ReadDirectoryChangesW(hDir,*buffer,SizeOf(FILE_NOTIFY_INFORMATION),#True,filter,bytesRead,ovlp,0) 
    Debug *buffer\Action
    Debug *buffer\FileNameLength
    
    Select *buffer\Action
      Case #FILE_ACTION_ADDED
      Case #FILE_ACTION_REMOVED
      Case #FILE_ACTION_MODIFIED
        Debug *buffer\Filename + " wurde modifiziert"
      Case #FILE_ACTION_RENAMED_OLD_NAME
      Case #FILE_ACTION_RENAMED_NEW_NAME
        
    EndSelect
        
    FreeMemory(*buffer)
    *buffer.FILE_NOTIFY_INFORMATION = AllocateMemory(SizeOf(FILE_NOTIFY_INFORMATION))
  Wend

EndProcedure

Example call

Code: Select all

WatchDirOrFile(GetCurrentDirectory())
Have fun with it!
Last edited by jpfiste on Fri Nov 05, 2010 4:25 pm, edited 1 time in total.
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Re: Anwendung ReadDirectoryChangesW

Post by Rings »

Geht das auch in english ?
SPAMINATOR NR.1
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Re: Anwendung ReadDirectoryChangesW

Post by gnozal »

Thanks jpfiste,
I packed all the pieces in one code snippet with some little changes.

Code: Select all

;
; Monitor Directory Changes
;
; 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
;
#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
; Notify info
Structure FILE_NOTIFY_INFORMATION
  NextEntryOffset.l
  Action.l
  FileNameLength.l
  Filename.s{255}
EndStructure
; Prototypes (dynamic loading : you may also import from kernel32.lib)
Prototype.i _ReadDirectoryChangesW(hDirectory.l, *lpBuffer,nBufferLength.l,bWatchSubtree.b,dwNotifyFilter.l,*lpBytesReturned,*lpOverlapped.OVERLAPPED,lpCompletionRoutine)
Global ReadDirectoryChangesW._ReadDirectoryChangesW
*kernel32dll = OpenLibrary(#PB_Any, "kernel32.dll")
If *kernel32dll
  ReadDirectoryChangesW = GetFunction(*kernel32dll, "ReadDirectoryChangesW")
  CloseLibrary(*kernel32dll)
EndIf
If ReadDirectoryChangesW = 0
  End 
EndIf
;
; FILE_NOTIFY_CHANGE_FILE_NAME     0x00000001	
; Any file name change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file.
; FILE_NOTIFY_CHANGE_DIR_NAME      0x00000002	
; Any directory-name change in the watched directory or subtree causes a change notification wait operation to return. Changes include creating or deleting a directory.
; FILE_NOTIFY_CHANGE_ATTRIBUTES    0x00000004	
; Any attribute change in the watched directory or subtree causes a change notification wait operation to return.
; FILE_NOTIFY_CHANGE_SIZE          0x00000008	
; Any file-size change in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change in file size only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.
; FILE_NOTIFY_CHANGE_LAST_WRITE    0x00000010	
; Any change to the last write-time of files in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change to the last write-time only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.
; FILE_NOTIFY_CHANGE_LAST_ACCESS   0x00000020	
; Any change to the last access time of files in the watched directory or subtree causes a change notification wait operation to return.
; FILE_NOTIFY_CHANGE_CREATION      0x00000040	
; Any change to the creation time of files in the watched directory or subtree causes a change notification wait operation to return.
; FILE_NOTIFY_CHANGE_SECURITY      0x00000100
;
Procedure WatchDirOrFile(DirectoryName.s, NotifyFilter.l = #FILE_NOTIFY_CHANGE_ALL)
  Protected buffer.FILE_NOTIFY_INFORMATION, ovlp.OVERLAPPED
  Protected FileAction_Filename.s
  ;
  hDir = CreateFile_(DirectoryName, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE | #FILE_SHARE_DELETE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
  If hDir
    ;
    While ReadDirectoryChangesW(hDir, @buffer, SizeOf(FILE_NOTIFY_INFORMATION), #True, NotifyFilter, bytesRead, ovlp, 0) 
      ;
      CompilerSelect #PB_Compiler_Unicode
        CompilerCase #True
          FileAction_Filename = buffer\Filename
        CompilerDefault
          FileAction_Filename = PeekS(@buffer\Filename, -1, #PB_Unicode)
      CompilerEndSelect
      Select buffer\Action
          ;
          ; FILE_ACTION_ADDED               0x00000001	
          ; The file was added to the directory.
          ; FILE_ACTION_REMOVED             0x00000002	
          ; The file was removed from the directory.
          ; FILE_ACTION_MODIFIED            0x00000003	
          ; The file was modified. This can be a change in the time stamp or attributes.
          ; FILE_ACTION_RENAMED_OLD_NAME    0x00000004	
          ; The file was renamed and this is the old name.
          ; FILE_ACTION_RENAMED_NEW_NAME    0x00000005	
          ; The file was renamed and this is the new name.
          ;
        Case #FILE_ACTION_ADDED
          Debug FileAction_Filename + " was added"
        Case #FILE_ACTION_REMOVED
          Debug FileAction_Filename + " was removed"
        Case #FILE_ACTION_MODIFIED
          Debug FileAction_Filename + " was modified"
        Case #FILE_ACTION_RENAMED_OLD_NAME
          Debug FileAction_Filename + " was renamed (old name)"
        Case #FILE_ACTION_RENAMED_NEW_NAME
          Debug FileAction_Filename + " was renamed (new name)"
      EndSelect
      ;
    Wend
    ;
    CloseHandle_(hDir)
  EndIf
  ;
EndProcedure
;
; E X A M P L E
;
Debug GetCurrentDirectory()
WatchDirOrFile(GetCurrentDirectory())
EDIT : added CloseHandle_(hDir).
Last edited by gnozal on Sat Nov 06, 2010 8:57 am, edited 1 time in total.
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
jpfiste
User
User
Posts: 18
Joined: Thu Feb 18, 2010 10:05 pm

Re: Anwendung ReadDirectoryChangesW

Post by jpfiste »

thanks
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Anwendung ReadDirectoryChangesW

Post by ts-soft »

thx for the good tip.

here a many shorter version of yours :wink:

Code: Select all

;
; Monitor Directory Changes
;
; 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
;
#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
; Notify info
Structure FILE_NOTIFY_INFORMATION
  NextEntryOffset.l
  Action.l
  FileNameLength.l
  Filename.s{255}
EndStructure

Import "kernel32.lib"
  ReadDirectoryChangesW(a, b, c, d, e, f, g, h)
EndImport

Procedure WatchDirOrFile(DirectoryName.s, NotifyFilter.l = #FILE_NOTIFY_CHANGE_ALL)
  Protected buffer.FILE_NOTIFY_INFORMATION, ovlp.OVERLAPPED
  Protected FileAction_Filename.s
  ;
  hDir = CreateFile_(DirectoryName, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE | #FILE_SHARE_DELETE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
  ;
  While ReadDirectoryChangesW(hDir, @buffer, SizeOf(FILE_NOTIFY_INFORMATION), #True, NotifyFilter, bytesRead, ovlp, 0)
    ;
    FileAction_Filename = PeekS(@buffer\Filename, -1, #PB_Unicode)
    
    Select buffer\Action
      Case #FILE_ACTION_ADDED
        Debug FileAction_Filename + " was added"
      Case #FILE_ACTION_REMOVED
        Debug FileAction_Filename + " was removed"
      Case #FILE_ACTION_MODIFIED
        Debug FileAction_Filename + " was modified"
      Case #FILE_ACTION_RENAMED_OLD_NAME
        Debug FileAction_Filename + " was renamed (old name)"
      Case #FILE_ACTION_RENAMED_NEW_NAME
        Debug FileAction_Filename + " was renamed (new name)"
    EndSelect
    ;
  Wend
  ;
EndProcedure
;
; E X A M P L E
;
Debug GetCurrentDirectory()
WatchDirOrFile(GetCurrentDirectory()) 
tested: x86 and x64 with ansi and unicode.

greetings
thomas
jpfiste
User
User
Posts: 18
Joined: Thu Feb 18, 2010 10:05 pm

revised version

Post by jpfiste »

Hello again,

this version of the FileSystem Watcher with ReadDirectoryChangedW can watch a single file AND fires the #FILE_ACTION_RENAMED_NEW_NAME Action.

Code: Select all

;
; Monitor Directory Changes
;
; 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
;
#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

; Notify info
Structure FILE_NOTIFY_INFORMATION
  NextEntryOffset.l
  Action.l
  FileNameLength.l
  Filename.s{32*1024}
EndStructure


; prototype for messaging on action
Prototype ActionCallback(filename.s, action.l)

; Callback variable for action calling
Define OnAction.ActionCallback

Import "kernel32.lib"
  ReadDirectoryChangesW(hDirectory.l, *lpBuffer.l, nBufferLength.l, bWatchSubtree.b, dwNotifyFilter.l, *lpBytesReturned.l, *lpOverlapped.OVERLAPPED, lpCompletionRoutine.l)
EndImport

ProcedureDLL SetFileSystemWatch(FileOrDirName.s, NotifyFilter.l = #FILE_NOTIFY_CHANGE_ALL)
  
  Shared ReadDirectoryChangesW, OnAction
  Protected *buffer.FILE_NOTIFY_INFORMATION, ovlp.OVERLAPPED
  Protected FileAction_Filename.s
  
  *buffer = AllocateMemory(SizeOf(FILE_NOTIFY_INFORMATION))
  
  ; Extract file information if present
  filename$ = GetFilePart(FileOrDirName)
  
  hDir = CreateFile_(GetPathPart(FileOrDirName),#FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
  If hDir
    ;
    While ReadDirectoryChangesW(hDir, *buffer, SizeOf(FILE_NOTIFY_INFORMATION), #True, NotifyFilter, bytesRead, ovlp, 0)
      
      CompilerSelect #PB_Compiler_Unicode
        CompilerCase #True
          FileAction_Filename = *buffer\Filename
        CompilerDefault
          FileAction_Filename = PeekS(@*buffer\Filename, -1, #PB_Unicode)
      CompilerEndSelect
      
      workFuther = #True  
      
      ; specific file should be watched
      If Len(filename$)
        If FileAction_Filename <> filename$
          workFuther = #False
        EndIf
      EndIf
          
      If workFuther = #True
        If OnAction
          OnAction(FileAction_Filename,*buffer\Action)
          
          If *buffer\NextEntryOffset
            *buffer + *buffer\NextEntryOffset
            
            CompilerSelect #PB_Compiler_Unicode
              CompilerCase #True
                FileAction_Filename = *buffer\Filename
              CompilerDefault
                FileAction_Filename = PeekS(@*buffer\Filename, -1, #PB_Unicode)
            CompilerEndSelect
            
            OnAction(FileAction_Filename,*buffer\Action)
          EndIf
          
        EndIf
      EndIf
      
      ; cleanup for next action
      FileAction_Filename = #NULL$
      *buffer\Filename = #NULL$
          
    Wend
    
    CloseHandle_(hDir)
  EndIf
  ;
EndProcedure

Procedure FileSystemAction(filename.s, action.l)
  
  Select action
    Case #FILE_ACTION_ADDED
      Debug filename + " added"
    Case #FILE_ACTION_MODIFIED
      Debug filename + " modified"
    Case #FILE_ACTION_REMOVED
      Debug filename + " deleted"
    Case #FILE_ACTION_RENAMED_NEW_NAME
      Debug filename + " -> new name"
    Case #FILE_ACTION_RENAMED_OLD_NAME
      Debug filename + " -> old name"
  EndSelect
  
EndProcedure


; now let's start
OnAction = @FileSystemAction()
SetFileSystemWatch("C:\Data\")
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Anwendung ReadDirectoryChangesW

Post by dige »

ts-soft wrote:thx for the good tip.

here a many shorter version of yours :wink:

Code: Select all

;
; Monitor Directory Changes
;
; 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
;
#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
; Notify info
Structure FILE_NOTIFY_INFORMATION
  NextEntryOffset.l
  Action.l
  FileNameLength.l
  Filename.s{255}
EndStructure

Import "kernel32.lib"
  ReadDirectoryChangesW(a, b, c, d, e, f, g, h)
EndImport

Procedure WatchDirOrFile(DirectoryName.s, NotifyFilter.l = #FILE_NOTIFY_CHANGE_ALL)
  Protected buffer.FILE_NOTIFY_INFORMATION, ovlp.OVERLAPPED
  Protected FileAction_Filename.s
  ;
  hDir = CreateFile_(DirectoryName, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE | #FILE_SHARE_DELETE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
  ;
  While ReadDirectoryChangesW(hDir, @buffer, SizeOf(FILE_NOTIFY_INFORMATION), #True, NotifyFilter, bytesRead, ovlp, 0)
    ;
    FileAction_Filename = PeekS(@buffer\Filename, -1, #PB_Unicode)
    
    Select buffer\Action
      Case #FILE_ACTION_ADDED
        Debug FileAction_Filename + " was added"
      Case #FILE_ACTION_REMOVED
        Debug FileAction_Filename + " was removed"
      Case #FILE_ACTION_MODIFIED
        Debug FileAction_Filename + " was modified"
      Case #FILE_ACTION_RENAMED_OLD_NAME
        Debug FileAction_Filename + " was renamed (old name)"
      Case #FILE_ACTION_RENAMED_NEW_NAME
        Debug FileAction_Filename + " was renamed (new name)"
    EndSelect
    ;
  Wend
  ;
EndProcedure
;
; E X A M P L E
;
Debug GetCurrentDirectory()
WatchDirOrFile(GetCurrentDirectory()) 
tested: x86 and x64 with ansi and unicode.

greetings
thomas
@TS-Soft: I'm afraid there a lot of sleeping bugs inside...

Code: Select all

  While ReadDirectoryChangesW(hDir, @buffer, SizeOf(FILE_NOTIFY_INFORMATION), #True, NotifyFilter, bytesRead, ovlp, 0)
What about NextEntryOffset, if there are more than one events? Buffersize to small?

Code: Select all

Buffer.FILE_NOTIFY_INFORMATION
Buffer is declared one times and will reused for every event but not cleared before.
Deleting 2 files ( #FILE_ACTION_REMOVE ) like ABCDEFG.jpg and then D.jpg will be D.jpgFG.jpg

just my 2 pence
"Daddy, I'll run faster, then it is not so far..."
dige
Addict
Addict
Posts: 1391
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Anwendung ReadDirectoryChangesW

Post by dige »

@TS-Soft: I'm afraid there a lot of sleeping bugs inside...

Code: Select all

  While ReadDirectoryChangesW(hDir, @buffer, SizeOf(FILE_NOTIFY_INFORMATION), #True, NotifyFilter, bytesRead, ovlp, 0)
What about NextEntryOffset, if there are more than one events? Buffersize to small?

Code: Select all

Buffer.FILE_NOTIFY_INFORMATION
Buffer is declared one times and will reused for every event but not cleared before.
Deleting 2 files ( #FILE_ACTION_REMOVE ) like ABCDEFG.jpg and then D.jpg will be D.jpgFG.jpg

just my 2 pence
"Daddy, I'll run faster, then it is not so far..."
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Anwendung ReadDirectoryChangesW

Post by ts-soft »

@jpfiste
you can use this in ascii or unicode, the compilerifs not required!

Code: Select all

FileAction_Filename = PeekS(@*buffer\Filename, -1, #PB_Unicode) 
@dige
the buffer is filled every loop, i see no problem without clearing but i have not read the msdn.
jpfiste
User
User
Posts: 18
Joined: Thu Feb 18, 2010 10:05 pm

Re: Anwendung ReadDirectoryChangesW

Post by jpfiste »

I extracted the source from a running project. May I forgot something - sorry for that. With this additions it should work. My program runs correctly.

The next Entry offset is used when more Items are changed (e.g. two files are deleted)

Code: Select all

If *buffer\NextEntryOffset
   *buffer + *buffer\NextEntryOffset
   ; read next filename from buffer
endif
This code works for me. If I delete more than one item I get all filenames correct.

The structure is cleared in every loop.

Code: Select all

ClearStructure(*buffer, FILE_NOTIFY_INFORMATION)
Addition:
If you want ReadDirectoryChangesW asynchronous you must initialize hDir with the following:

Code: Select all

*ovlp = AllocateMemory(SizeOf(OVERLAPPED))
hDir = CreateFile_(GetPathPart(*params\directory$),#FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS | #FILE_FLAG_OVERLAPPED, #Null)
Hope this helps
User avatar
HAnil
User
User
Posts: 87
Joined: Thu Feb 26, 2004 5:42 pm
Location: 28:58E 41:01N

Re: Anwendung ReadDirectoryChangesW

Post by HAnil »

Hi jpfiste,
how can we use your additional code ?
I tried async mode detection, but is not working for me.
Maybe I was wrong somethings.

added code is

Code: Select all

  ovlp = AllocateMemory(SizeOf(OVERLAPPED))
  hDir = CreateFile_(DirectoryName,#FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE,                      #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS | #FILE_FLAG_OVERLAPPED, #Null)

thanks for your helps.
PureBasic v5.22 LTS & Mac & Windows8
jpfiste
User
User
Posts: 18
Joined: Thu Feb 18, 2010 10:05 pm

Re: Anwendung ReadDirectoryChangesW

Post by jpfiste »

I think it should work. The only think is you have to do. Replace the following line

Code: Select all

  ; synchrous (not overlapped)
  hDir = CreateFile_(directory$, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
with this:

Code: Select all

 ; async (overlapped)
ovlp = AllocateMemory(SizeOf(OVERLAPPED))
hDir = CreateFile_(directory$ ,#FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS | #FILE_FLAG_OVERLAPPED, #Null)

Remember that you are in a loop. The async-mode means that the ReadDirectoryChangesW returns immediately. Place a little delay at the end of the loop. Then it should work and the changed filename is reported within my code (I've tested it).

Code: Select all

 Delay(20)
Wend; Readdirchange
Hope this helps.
Post Reply