我应该如何读取 FILE_NOTIFY_INFORMATION 结构中的文件名

How should I read the filename in FILE_NOTIFY_INFORMATION struct

我正在尝试监视文件更改,但我不太确定如何读取 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. 根据 ReadDirectoryChangesW 函数的文档,缓冲区需要 DWORD 对齐。由于您在堆栈上使用缓冲区,因此无法保证这一点 - 您应该从堆中分配一个缓冲区。

  2. 您似乎没有正确使用该功能。通常你会先调用 ReadDirectoryChangesW,然后 然后 等待事件。不是相反。当 ReadDirectoryChangesW returns 用于异步调用时,此时缓冲区中通常没有数据。在使用缓冲区内容之前,您需要等待请求已完成的通知。

  3. FindNextChangeNotification只和FindFirstChangeNotification一起使用,所以这是完全错误的。 ReadDirectoryChangesW 完成后,您需要使用 FILE_NOTIFY_INFORMATION 结构中的 NextEntryOffset 字段来循环返回的事件。

编辑:由于您向问题添加了更多代码,现在很明显您正在混合使用两个 API。 FindFirstChangeNotificationFindNextChangeNotification 是一个 API,ReadDirectoryChangesW 是另一个。我相信您对文档中的这段话感到困惑:

This function does not indicate the change that satisfied the wait condition. To retrieve information about the specific change as part of the notification, use the ReadDirectoryChangesW function.

我想你的困惑是可以理解的,但是这两个 API 不能一起使用。如果您正在使用 FindFirstChangeNotification,那么您得到的只是一个通知,表明 某些内容 已更改,并且您必须重新读取目录以找出它是什么。如果您想要文件级别的特定通知,则必须使用 ReadDirectoryChangesW 进行监控。