Introduction

Windows applications can do dynamic monitoring of any specified directory.
Once changes have occurred and are detected, the spy application can run
various tasks ( run antivirus, log activity, determine more information about
changes, call other tasks etc).

Win 32 API provides three functions that are based on the events:

FindFirstChangeNotification

FindNextChangeNotification

FindCloseChangeNotification

ReadDirectoryChangesW

These allow creating watchdog or spying applications.

How to create

First of all spy application should call FindFirstChangeNotification
to create event handler to monitor changes specified as the functions
parameters.

The result of FindFirstChangeNotification can be passed as
parameter in to WaitForSingleObject and when specified event has
occurred, application can do various actions such as: antivirus starting, adding
record to the log file, and so on. Note that this function does not detect
changes, it only creates synchronization event and marks it if changes are made.
After our spy application handles changes, it should call
FindNextChangeNotification to continue monitoring or
FindCloseChangeNotification to finish it.

Win32 API provides also ReadDirectoryChangesW that can operate
with following filters (MSDN) :

FILE_NOTIFY_CHANGE_FILE_NAME

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

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

Any attribute change in the watched directory or subtree causes a change
notification wait operation to return.

FILE_NOTIFY_CHANGE_SIZE

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

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

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

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

Any security-descriptor change in the watched directory or subtree causes a
change notification wait operation to return.

Conclusion

The attached Demo application starts separate threads to monitor all possible
changes in the "c:\\Program Files" directory and shows occurred
notifications and its date/time in the List control. Demo application shows also
how to use ReadDirectoryChangesW and compare both methods
visually.

Functionality of the Demo application can be extended to determine concrete
changes, to log changes in to file, run external applications or tasks on the
specified event, use described methods as system service and so on. Readers have
full freedom to modify and use the demo project.

The example is good, but fails to take into account that the buffer returned is populated with an array of changes. not just one - the code does not show iterating over the list of objects.

If there are no objections I will paste just the code changes in here:

FILE_NOTIFY_INFORMATION *pRecord = Buffer;
do
{
switch(pRecord->Action)
{
case FILE_ACTION_ADDED: helper_txt = "The file was added to the directory"; break;
case FILE_ACTION_REMOVED: helper_txt = "The file was removed from the directory"; break;
case FILE_ACTION_MODIFIED: helper_txt = "The file was modified. This can be a change in the time stamp or attributes."; break;
case FILE_ACTION_RENAMED_OLD_NAME: helper_txt = "The file was renamed and this is the old name."; break;
case FILE_ACTION_RENAMED_NEW_NAME: helper_txt = "The file was renamed and this is the new name."; break;
}

if (0== pRecord->NextEntryOffset)
break;
// point to next record in array
pRecord = (FILE_NOTIFY_INFORMATION *)(&((unsigned char*)Buffer)[pRecord->NextEntryOffset]);
} while (TRUE);

I have however found that the watchers seem to be locking changes on the actual directory opened. I found the case for this, is in the way the directory is opened before watching - will prevent anyone from adding folders or files, simple to fix: add
FILE_SHARE_WRITE
to the open flags when opening the directory handle
Enjoy

Conrad -
The world waits for you to stick your neck out, it's not easy. But once you actually stand up, you do get noticed.
http://www.plcsimulator.org/

I just have a little question. Is it possible to know the new path of a file which has been moved ? For example: if i have this directory "C:\TestFileSpy\" and this file "C:\TestFileSpy\Temp.txt", then i move "Temp.txt" to my desktop. how can i get the new path ( "C:\Users\Propietario\Desktop\Temp.txt" ) ?