(Updated with simpler code)
I'm using ReadDirectoryChangesW() to watch for changes to certain folders. It works correctly when a file is created in one of the watched folders, but when a subdirectory is created it is never notified.
For example, if I watch the path c:\testA\testB and create a file in that folder, then ReadDirectoryChangesW() works correctly. If I instead create a directory in that folder, then WaitForSingleObjectEx doesn't ever return.
Interestingly, if I instead watch c:\testA and create a directory under c:\testA\testB then WaitForSingleObjectEx returns as expected. Note that I am not watching subfolders, (bWatchSubtree == false) so this result is very strange.
One possible solution is to watch two folders for every folder that I want to monitor, the folder itself for file changes, and the parent folder for any subdirectory changes, but you can see why that is tedious.
Here is some sample code to reproduce the problem:
HANDLE watchDir(const char* dirPath)
{
HANDLE dir = CreateFile(
dirPath,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
const size_t kBufferSize = 32 * 1024;
char buffer[kBufferSize];
OVERLAPPED overlap;
memset(&overlap, 0, sizeof(overlap));
memset(&buffer, 0, sizeof(buffer));
overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (ReadDirectoryChangesW(
dir,
buffer,
sizeof(buffer),
FALSE, /* bWatchSubtree = false, we only watch one folder*/
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION,
NULL,
&overlap,
NULL) != 0)
{
return overlap.hEvent;
}
else
{
return nullptr;
}
}
void main(int nargs, const char* args)
{
HANDLE watchHandle = watchDir("C:\\testA\\testB");
if (watchHandle == nullptr)
{
cout << "Failed to issue watch command" << endl;
return;
}
DWORD result = WaitForSingleObjectEx(watchHandle, INFINITE, false);
// This code will never be reached when creating a dir in c:\testA\testB, but it WILL if a file is created in that folder.
cout << "Done waiting for dir: " << result << endl;
}
Running this code and making a new file at c:\testA\testB\newfile.txt yields this output:
c:\testA\testB modified.
Running this code and making a new directory at c:\testA\testB\newdir is never woken up.
Why does creating a directory cause a notification for two folders up? Why not just the parent? Why should creating a file and creating a folder act differently at all?