Почему ReadDirectoryChangesW не запускается правильно, когда подкаталог создается в наблюдаемом каталоге?

(Обновлено с более простым кодом)

Я использую ReadDirectoryChangesW(), чтобы отслеживать изменения в определенных папках. Он работает правильно, когда файл создается в одной из просматриваемых папок, но когда создается подкаталог, он никогда не уведомляется.

Например, если я смотрю путь c:\testA\testB и создаю файл в этой папке, то ReadDirectoryChangesW() работает правильно. Если я вместо этого создаю каталог в этой папке, то WaitForSingleObjectEx никогда не вернется.

Интересно, что если я вместо этого наблюдаю за c: \ testA и создаю каталог в каталоге c:\testA\testB, тогда WaitForSingleObjectEx возвращается, как и ожидалось. Обратите внимание, что я не смотрю подпапки (bWatchSubtree == false), поэтому этот результат очень странный.

Одним из возможных решений является просмотр двух папок для каждой папки, которую я хочу отслеживать, самой папки для изменений файлов и родительской папки для любых изменений подкаталогов, но вы можете понять, почему это утомительно.

Вот пример кода для воспроизведения проблемы:

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;
}

Запуск этого кода и создание нового файла в c:\testA\testB\newfile.txt приводит к следующим выводам:

c:\testA\testB modified.

Запуск этого кода и создание нового каталога в c:\testA\testB\newdir никогда не просыпается.

Почему создание каталога вызывает уведомление для двух папок вверх? Почему не только родитель? Почему создание файла и папки должны действовать по-другому?

0 ответов

Другие вопросы по тегам