I'm trying to monitor file changes but I am not really sure on how to read the filename in the FILE_NOTIFY_INFORMATION struct:
HANDLE dwChangeHandles[2];
DWORD dwWaitStatus;
wChangeHandles[0] = FindFirstChangeNotification(dirname.c_str(), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);
if (dwChangeHandles[0] == INVALID_HANDLE_VALUE) printerr(__FILE__,__LINE__,"FindFirstChangeNotification function failed.\n");
...
if ((dwChangeHandles[0] == NULL) || (dwChangeHandles[1] == NULL)) //final validation
printerr(__FILE__,__LINE__,"Unexpected NULL from FindFirstChangeNotification.\n");
while (TRUE) {
std::cout << "Waiting for notification...\n";
dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, FALSE, INFINITE);
if(dwWaitStatus==WAIT_OBJECT_0){
std::cout << "Something changed\n";
DWORD BytesReturned;
size_t bufLen = 1024;
FILE_NOTIFY_INFORMATION buffer[bufLen];
if (ReadDirectoryChangesW(dwChangeHandles[0], buffer, bufLen, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &BytesReturned, NULL, NULL)){
std::wcout << std::wstring(buffer->FileName)<< std::endl; //THERE IS NOTHING IN THE EXPECTED OUTPUT HERE
}
if (FindNextChangeNotification(dwChangeHandles[0]) == FALSE ) printerr(__FILE__,__LINE__,"FindNextChangeNotification function failed.\n");
}
else if(dwWaitStatus==WAIT_TIMEOUT) printerr(__FILE__,__LINE__,"No changes in the timeout period.\n");
else printerr(__FILE__,__LINE__,"Unhandled dwWaitStatus.\n");
}
Is there something I am doing wrong
You have a number of problems that I can see immediately:
According to the docs for the
ReadDirectoryChangesW
function, the buffer needs to beDWORD
-aligned. As you are using a buffer on the stack this isn't guaranteed - you should allocate one from the heap instead.You don't seem to be using the function correctly. Normally you would call
ReadDirectoryChangesW
first, and then wait on the event. Not the other way around. WhenReadDirectoryChangesW
returns for an asynchronous call there is usually no data in the buffer at that point. You need to wait for notification that the request has been completed before using the buffer contents.FindNextChangeNotification
is only used withFindFirstChangeNotification
, so this is completely wrong. When theReadDirectoryChangesW
completes you need to use theNextEntryOffset
field in theFILE_NOTIFY_INFORMATION
structure to loop through the returned events.Edit: Since you've added more code to your question it's now obvious that you are mixing the two APIs.
FindFirstChangeNotification
andFindNextChangeNotification
are one API, andReadDirectoryChangesW
is another. I believe you've been confused by this passage in the docs:I guess your confusion is understandable, but the two APIs can't be used together. If you're using
FindFirstChangeNotification
then all you get is a notification that something changed, and you have to re-read the directory to find out what it was. If you want specific notifications at the file level then you have to useReadDirectoryChangesW
to do the monitoring.