Как мне прочитать имя файла в структуре FILE_NOTIFY_INFORMATION

Я пытаюсь отслеживать изменения файлов, но я не совсем уверен, как прочитать имя файла в структуре FILE_NOTIFY_INFORMATION:

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

Есть ли что-то, что я делаю не так

1 ответ

Решение

У вас есть ряд проблем, которые я вижу сразу:

  1. Согласно документам для ReadDirectoryChangesW функция, буфер должен быть DWORD -aligned. Поскольку вы используете буфер в стеке, это не гарантируется - вместо этого вы должны выделить его из кучи.

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

  3. FindNextChangeNotification используется только с FindFirstChangeNotification так что это совершенно неправильно. Когда ReadDirectoryChangesW завершает вам нужно использовать NextEntryOffset поле в FILE_NOTIFY_INFORMATION структура, чтобы пройти через возвращенные события.

Изменить: так как вы добавили больше кода в свой вопрос, теперь очевидно, что вы смешиваете два API. FindFirstChangeNotification а также FindNextChangeNotification один API, и ReadDirectoryChangesW Другой. Я полагаю, что вы были смущены этим отрывком из документации:

Эта функция не указывает на изменение, которое удовлетворяло условию ожидания. Чтобы получить информацию о конкретном изменении как часть уведомления, используйте функцию ReadDirectoryChangesW.

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

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