【发布时间】:2016-10-23 05:06:55
【问题描述】:
我正在向我的(基于 Qt 的)应用程序添加功能,以递归地监视我的 Windows 系统上的任意文件夹的 any 活动(Qt 变体 QFileSystemWatcher 缺少的东西)。使用 CreatFileW() 打开文件夹后,我创建了一个完成端口来接收重叠的 I/O,然后我使用 ReadDirectoryChangesW() 将读取排队。
我已将所有这些放在以下“简单”Win32 控制台应用程序中进行演示(请注意,“stdafx.h”标头已修改为包含“windows.h”,但与 Visual Studio 2013 IDE 不同生成它):
#include "stdafx.h"
#define MAX_BUFFER 4096
struct ThreadData
{;
DWORD winerr;
HANDLE handle;
unsigned int flags;
int recursive;
HANDLE completion_port;
CHAR buffer[MAX_BUFFER];
DWORD buffer_len;
OVERLAPPED overlapped;
};
int _tmain(int argc, _TCHAR* argv[])
{
DWORD winerr;
ThreadData td;
td.flags = FILE_NOTIFY_CHANGE_FILE_NAME|
FILE_NOTIFY_CHANGE_DIR_NAME|
FILE_NOTIFY_CHANGE_ATTRIBUTES|
FILE_NOTIFY_CHANGE_SIZE|
FILE_NOTIFY_CHANGE_LAST_WRITE|
FILE_NOTIFY_CHANGE_LAST_ACCESS|
FILE_NOTIFY_CHANGE_CREATION|
FILE_NOTIFY_CHANGE_SECURITY;
td.recursive = 1;
td.completion_port = INVALID_HANDLE_VALUE;
td.handle = INVALID_HANDLE_VALUE;
td.handle = CreateFileW(L"J:\\Font", // arbitrary folder
FILE_LIST_DIRECTORY, // required
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
// Use FILE_FLAG_OVERLAPPED for asynchronous operation with ReadDirectoryChangesW.
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
if(td.handle == INVALID_HANDLE_VALUE)
{
winerr = GetLastError();
CloseHandle(td->handle);
return 0;
}
td.completion_port = CreateIoCompletionPort(td.handle,
td.completion_port,
(ULONG_PTR)td,
0); // max num processors
if(td.completion_port == INVALID_HANDLE_VALUE)
{
winerr = GetLastError();
CloseHandle(td.completion_port);
CloseHandle(td.handle);
return 0;
}
BOOL rdc = ReadDirectoryChangesW(td.handle,
td.buffer, // read results
MAX_BUFFER,
td.recursive, // watch subdirectories
// NOTE: At least one flag is required!
td.flags, // see Notify Filters below
&td.buffer_len,
&td.overlapped,
NULL); // completion routine
if(rdc == 0)
{
winerr = GetLastError(); // "The handle is invalid. (0x6)"
CloseHandle(td.completion_port);
CloseHandle(td.handle);
return 0;
}
// Launch thread here to handle completions and trigger new ones
...
// Clean up when the thread is done
CloseHandle(td.completion_port);
CloseHandle(td.handle);
return 0;
}
关于这段代码需要注意的是,它是在一个 Python 模块(“watcher”)之后建模的,用 C 语言编写,提供与 Python 环境类似的功能。我已经在 Python 中使用过它,它在这个 C++ 片段中的所有相同设置下都能正常工作。
在上述代码中,CreateIoCompletionPort() 接受 CreateFileW() 生成的 HANDLE,但 ReadDirectoryChangesW() 不接受。它返回 0,GetLastError() 返回“句柄无效。(0x6)”。我已经在 32 位和 64 位编译下都试过了,以防万一(我使用的是 64 位版本的 Python)。此外,指定的目录似乎无关紧要:我指定的所有目录都会产生相同的结果,这表明某处的设置有问题。
CreateFileW() 调用中是否有某些内容可能导致 HANDLE 对生成完成端口有效,但会给 ReadDirectoryChangesW() 函数带来胃痛?
【问题讨论】:
-
您的
OVERLAPPED结构看起来未初始化。