ReadDirectoryChangesW 从不调用回调

问题描述 投票:0回答:1

我有一些代码永远不会调用回调,即使我复制、更改或删除 C:\Temp 中的文件也是如此。我究竟做错了什么? 它似乎停留在 WaitForSingleObject 并且根本不调用 DirectoryChangeCallback。

StackOverflow 要求我添加更多细节,因为我的问题主要是代码,所以我在这里多写一些。该程序应该易于理解且完整,因此在您尝试时应该会运行。

#include <windows.h>
#include <wininet.h>
#include <shlwapi.h>

#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "shlwapi.lib")

#include <string>

VOID CALLBACK DirectoryChangeCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
    ASSERT(FALSE); // program never comes here
}


int main() {
    std::wstring path = L"C:\\Temp";

    // Set up a directory change notification
    HANDLE hDirectory = CreateFileW(path.c_str()
                                    , GENERIC_READ
                                    , FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
                                    , NULL
                                    , OPEN_EXISTING
                                    , FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED
                                    , NULL);
    if(hDirectory == INVALID_HANDLE_VALUE) {
        // Handle error
        return 1;
    }

    BYTE buffer[4096];  // Buffer to receive notification information
    DWORD dwBytesReturned;
    OVERLAPPED overlapped= {};
    overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if(overlapped.hEvent == NULL) {
        // Handle error
        CloseHandle(hDirectory);
        return 1;
    }

    // Start monitoring for changes
    DWORD dwNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME  | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE /*FILE_NOTIFY_CHANGE_SECURITY| FILE_NOTIFY_CHANGE_ATTRIBUTES*/;
    if(!ReadDirectoryChangesW(hDirectory, buffer, sizeof(buffer), TRUE/*subtree*/, dwNotifyFilter, NULL, &overlapped, DirectoryChangeCallback)) {
        if(GetLastError() != ERROR_IO_PENDING) {
            // Handle error
            CloseHandle(overlapped.hEvent);
            CloseHandle(hDirectory);
            return 1;
        }
    }

    // Wait for changes and process notifications in the callback function
    wprintf(L"Wait for single object\n");
    DWORD dwWaitResult = WaitForSingleObject(overlapped.hEvent, INFINITE); // *** STUCK HERE ***
    wprintf(L"result %d\n", int(dwWaitResult));


    // Clean up resources
    CloseHandle(overlapped.hEvent);
    CloseHandle(hDirectory);

    return 0;
}
c++ winapi
1个回答
0
投票

正如@RbMm所说,您对CreateFileW的使用与ReadDirectoryChangesW的使用不匹配。
ReadDirectoryChangesW函数中也提到了三种异步方式,但没有一种与代码相同。

  • 使用 GetOverlappedResult 函数。要通过 GetOverlappedResult 接收通知,请不要在
    中指定完成例程 lpCompletionRoutine 参数。一定要设置 hEvent 成员
    OVERLAPPED 结构到一个独特的事件。
  • 使用 GetQueuedCompletionStatus 函数。要通过 GetQueuedCompletionStatus 接收通知,请不要指定 lpCompletionRoutine 中的完成例程。关联目录 通过调用
    来处理带有完成端口的 hDirectory CreateIoCompletionPort 函数。
  • 使用完成例程。要通过完成例程接收通知,请不要将目录与完成相关联
    港口。在 lpCompletionRoutine 中指定完成例程。这
    每当操作完成或
    当线程处于可警告等待状态时取消。事件
    OVERLAPPED 结构的成员没有被系统使用,所以你
    可以自己用。

异步示例:CloudMirror
同步示例:fileserviceservice

© www.soinside.com 2019 - 2024. All rights reserved.