posted by Rodney Holiman on Tue 15th Jun 2004 19:19 UTC
"Monitor Class, Page 2/4"
FILE_ACTION_ADDED The file was added to the directory.
FILE_ACTION_REMOVED The file was removed from the directory.
FILE_ACTION_MODIFIED The file was modified. This can be a change in the time stamp or attributes.
FILE_ACTION_RENAMED_OLD_NAME The file was renamed and this is the old name.
FILE_ACTION_RENAMED_NEW_NAME The file was renamed and this is the new name.

Figure 2 - Possible values for the Action field.

The nBufferLength parameter is the size in bytes of lpBuffer.

The bWatchSubtree is a Boolean value that tells the function to watch sub-directories.

The dwNotifyFilter a bit mask that tells the function what events to look for. The values for this function are in figure 3.

FILE_NOTIFY_CHANGE_FILE_NAME Any filename change includes renaming, creating, or deleting a file.
FILE_NOTIFY_CHANGE_DIR_NAME Any directory name change includes creating or deleting a directory.
FILE_NOTIFY_CHANGE_ATTRIBUTES Any file attribute change.
FILE_NOTIFY_CHANGE_SIZE Any file-size change. Caching may delay this notification.
FILE_NOTIFY_CHANGE_LAST_WRITE Any change to the last write-time. Caching may delay this notification.
FILE_NOTIFY_CHANGE_LAST_ACCESS Any change to the last access time.
FILE_NOTIFY_CHANGE_CREATION Any change to the creation time.
FILE_NOTIFY_CHANGE_SECURITY Any security-descriptor change.

Figure 3 - dwNotifyFilter options.

The lpBytesReturned parameter is the number of bytes written to the lpBuffer parameter when thefunction is used in synchronous calls. This parameter is undefined when the function is used in asynchronous calls (read on for more information on synchronous versus asynchronous calls).

The lpOverlapped parameter is a pointer to an TOverlapped record.

The lpCompletionRoutine parameter is a function pointer to an IO completion routine.  An IO completion routine prototype is defined in figure 4.

procedure FileIOCompletionRoutine(dwErrorCode : DWORD;
                                  dwNumberOfBytesTransfered : DWORD;
                                  lpOverlapp : POVERLAPPED) Stdcall; 

Figure 4 - An IO completion routine prototype.

Calling ReadDirectoryChangesW

There are two was to call ReadDirectoryChangesW, synchronous or asynchronous. As you might expect when calling ReadDirectoryChangesW synchronously it does not return until one of the events you are looking for happens. This is the easiest way to call ReadDirectoryChangesW but I have found it to be the least effective way to use the function.  I have included an example project that show how to use ReadDirectoryChangesW synchronously. The TDirectoryMonitor class uses the asynchronous method to call ReadDirectoryChangesW.

The TDirectoryMonitor class.

The TDirectoryMonitor class is described in figure 5. The TDirectoryMonitor class hides all of the details about ReadDirectoryChangesW from the caller.  The class exposes only two methods, four properties and one event. The two methods are Start and Stop. The Start method begins directory monitoring; the Stop method ends the monitoring. The properties are DirectoryToWatch, WatchSubFolders, Options, and WorkerThread. The DirectoryToWatch property defines the directory to watch.  The WatchSubFolder property defines if the class will notify the caller if an event occurs on a sub-directory.

TDirectoryMonitor = Class(TObject)
Private
  FDirectoryToWatch : String;
  FWorkerThread : TWorkerThread;
  FOnDirectoryChange : TDirectoryChange;
  FWindowHandle : THandle;
  FOptions : TActionsToWatch;
  FWatchSubFolders : Boolean;
  procedure InternalWinProc(var Msg : TMessage);
  procedure SetDirToWatch(Value : String); Public
  procedure Start;
  procedure Stop;
  Constructor Create;
  Destructor Destroy; override;
  Property WorkerThread : TWorkerThread Read FWorkerThread;
  Property DirectoryToWatch : String Read FDirectoryToWatch Write SetDirToWatch; Published
  Property OnDirectoryChange : TDirectoryChange Read FOnDirectoryChange Write FOnDirectoryChange;
  Property Options : TActionsToWatch Read FOptions Write FOptions;
  Property WatchSubFolders : Boolean Read FWatchSubFolders Write FWatchSubFolders Default True; end;

Figure 5 - The TDirectoryMonitor Class.

The two less obvious properties are the OptionsOptions and the WorkerThread. The Options property is a set of TActionToWatch. TActionToWatch is an enumerated type that corresponds to the constants defined in figure  3. This property is not defaulted. It is left as an exercise for the reader to add defaults. The definition of TActionToWatch is shown in figure 6.

TActionToWatch = (awChangeFileName,awChangeDirName,awChangeAttributes,awChangeSize,
                  awChangeLastWrite,awChangeLastAccess,awChangeCreation,awChangeSecurity);

TActionsToWatch = Set Of TActionToWatch; 

Figure 6 - TActionToWatch

The WorkerThread property is a class of TWorkerThread. TWorkerThread is a descendant of TThread. Why a thread? To explain that a fuller explanation of ReadDirectoryChangesW is needed. The ReadDirectoryChangesW function can be called one of two ways, synchronously or asynchronously. If called synchronously, the ReadDirectoryChangesW funcion doesn't return until an event occurs. An asynchronous call the function return immediately and event notification is done through a completion port, a callback function, or overlapped I/O. To be able to receive these asynchronous notifications the thread that calls ReadDirectoryChangesW must be put in an alertable state. The up shot of both of these methods is that the calling thread is stopped until an event occurs. For a component to suspend the main thread is at best unexpected, at worst unacceptable. The WorkerThread takes care of this problem by creating a new thread outside the main thread. That way the main thread can continue while the worker thread waits for an event.

Table of contents
  1. "Monitor Class, Page 1/4"
  2. "Monitor Class, Page 2/4"
  3. "Monitor Class, Page 3/4"
  4. "Monitor Class, Page 4/4"
e p (0)    16 Comment(s)

Related Articles

posted by Alexandru Lazar on Mon 5th Jan 2009 19:13
posted by Kroc Camen on Sat 27th Dec 2008 20:52
posted by Thom Holwerda on Fri 26th Dec 2008 11:26, submitted by poundsmack