I want to watch for changes done with a file (the event i'm waiting for is change contents event, i.e. last modified date is updated)
I have a code like this (minimalized example of actual code)
I expect that each iteration of the while loop the event gets reset and is available to be fired again but that doesn't happen
Why it fires change event only once?
int main()
{
const wchar_t *dir_path = L"C:\\Users\\IC\\AppData\\Roaming\\JetBrains\\CLion2021.3\\scratches\\";
HANDLE hDir = ::CreateFileW(
dir_path,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL
);
FILE_NOTIFY_INFORMATION fni;
OVERLAPPED overlapped;
overlapped.hEvent = ::CreateEventA(NULL, FALSE, FALSE, NULL);
::ReadDirectoryChangesW(
hDir,
&fni,
sizeof(fni),
TRUE,
FILE_NOTIFY_CHANGE_LAST_WRITE,
NULL,
&overlapped,
NULL
);
while (true)
{
std::vector<HANDLE> all_job_event_handles;
if (::ResetEvent(overlapped.hEvent) == FALSE)
{
printf("ResetEvent failed\n");
fflush(stdout);
return 1;
}
all_job_event_handles.push_back(overlapped.hEvent);
DWORD result = ::WaitForMultipleObjects(all_job_event_handles.size(), all_job_event_handles.data(), FALSE, INFINITE);
if (result == WAIT_FAILED)
{
printf("WaitForMultipleObjects failed\n");
fflush(stdout);
return 1;
}
if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 all_job_event_handles.size())
{
printf("file changed\n");
fflush(stdout);
}
}
}
CodePudding user response:
Because that's just not how ReadDirectoryChanges
works. It doesn't continuously send you changes. It sends you one batch of changes. You process them. You call the function again to tell the system that you want more changes.
I found a correct usage example of the function here: https://gist.github.com/nickav/a57009d4fcc3b527ed0f5c9cf30618f8
Some side notes:
- You don't check whether
ReadDirectoryChanges
succeeds. This is bad; if it failed, you will hang on the Wait call forever. - You don't zero-initialize the
OVERLAPPED
structure. - You create the event as an auto-reset event (second parameter is
FALSE
).ResetEvent
on such an event does nothing. - All the event handles you add into your vector are the same event object. You just have an ever-growing list of the same event repeatedly that you pass to
WaitForMultipleObjects
. This does nothing at best, but will eventually fail becauseWFMO
doesn't allow more thanMAXIMUM_WAIT_OBJECTS
handles, and this number is fairly low (32, I think). - You probably want a more permissive share mode on the directory you open.