posted by Rodney Holiman on Tue 15th Jun 2004 19:19 UTC
IconThere are times when a directory needs watched.  For reasons of its own, a program may need to know when a file is deleted, updated or renamed.  If .NET is involved, this is a trivial task.  Create an instance of the FileSystemWatcher; set some properties, and the task is completed.  If a non .NET solution is required (and regardless of the hype, some people haven’t embraced .NET in all of its glory.), the ReadDirectoryChangesW function must be used, however the documentation for ReadDirectoryChangesW is sketchy at best.

In an effort to make ReadDirectoryChangesW less of a mystery, this article will briefly explain the ReadDirectoryChangesW function, present a class for Delphi that encapsulates the ReadDirectoryChangesW function and provide an example program that shows how to use the class to monitor a directory for updates, deletes or renames of files in the directory.

(Note : All code in this article has been tested with Delphi 6 and 7, but I can’t think of any reason it won’t work with Delphi 4 or 5 if you declare the function prototype yourself. Delphi 8 is a pure .NET environment, so if you are using Delphi 8 use the FileSystemWatcher class.)

The ReadDirectoryChangesW Function.

At the heart of the class lies the ReadDirectoryChangesW function.  The function monitors a directory and alerts the caller when certain events occur.  It is important to note that the ReadDirectoryChangesW function will only work on Windows NT, 2000 and XP.  The function will not work on any other version of Windows.  The ReadDirectoryChangesW function is defined in the Windows.pas unit in Delphi as :

function ReadDirectoryChangesW(hDirectory: THandle;
                                lpBuffer: Pointer;
                                nBufferLength: DWORD;
                                bWatchSubtree: Bool; 
                                dwNotifyFilter: DWORD;
                                lpBytesReturned: LPDWORD;
                                lpOverlapped: POverlapped;
                                lpCompletionRoutine: FARPROC): BOOL;

Lets examine the parameters of ReadDirectoryChangesW and look at how the function is called.

The parameters

The hDirectory is the handle of the directory to be watched.  This handle is obtained by calling the CreateFile function with the FILE_LIST_DIRECTORY flag.

The lpBuffer parameter is a pointer to a list of File_Notify_Information records.  The Delphi definition of File_Notify_Information is shown in Figure 1. The File_Notify_Information record contains four fields.  The first is NextEntryOffset. This field contains the number of bytes to the next record.  A value of zero indicates the last record in the list.  The second field is the Action field. The action field holds a value that describes the type of change that occurred.  The possible values for this field are described in Figure 2.  The third field is FileNameLength. The FileNameLength is the length of the filename in bytes (not chars).  This field does not include the null terminating character.  The last field in the File_Notify_Information record is FileName. This contains the name of the file that was effected.  There is no null terminator, and it is unspecified if the field will have the long or short filename, but during all of my testing it always had the long filename.

TFileNotifyInformation = Record
                             NextEntryOffset : DWORD;
                             Action : DWORD;
                             FileNameLength : DWORD;
                             FileName : Array[0..MAX_PATH] OfWCHAR;

PFileNotifyInformation = ^TFileNotifyInformation; 

Figure 1 - The File_Notify_Information record

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)

Technology White Papers

See More