0

(用更简单的代码更新)

我正在使用 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 创建一个新目录永远不会被唤醒。

为什么创建目录会导致两个文件夹的通知?为什么不只是父母?为什么创建文件和创建文件夹的行为完全不同?

4

0 回答 0