FILE_ACTION_ADDEDThe file was added to the directory. FILE_ACTION_REMOVEDThe file was removed from the directory. FILE_ACTION_MODIFIEDThe file was modified. This can be a change in the time stamp or attributes. FILE_ACTION_RENAMED_OLD_NAMEThe file was renamed and this is the old name. FILE_ACTION_RENAMED_NEW_NAMEThe 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.
- "Monitor Class, Page 1/4"
- "Monitor Class, Page 2/4"
- "Monitor Class, Page 3/4"
- "Monitor Class, Page 4/4"


