gpt4 book ai didi

c++ - ReadDirectoryChangesW 拒绝 CreateIoCompletionPort 接受的 HANDLE

转载 作者:行者123 更新时间:2023-11-27 22:48:38 25 4
gpt4 key购买 nike

我正在向我的(基于 Qt 的)应用程序添加功能,以递归地监视我的 Windows 系统上的任意文件夹的任何事件(这是 Qt 变体 QFileSystemWatcher 所缺少的)。使用 CreatFileW() 打开文件夹后,我创建了一个完成端口来接收重叠的 I/O,然后使用 ReadDirectoryChangesW() 对读取进行排队。

我已将所有这些放在下面的“简单”Win32 控制台应用程序中进行演示(请注意,“stdafx.h” header 已被修改为包含“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;
}

关于此代码需要注意的一点是,它是根据用 C 语言编写的 Python 模块(“watcher”)建模的,该模块提供与 Python 环境类似的功能。我已经在 Python 中使用过它,并且在这个 C++ 片段中使用所有相同的设置,它可以按预期工作。

在上面的代码中,CreateIoCompletionPort()接受了CreateFileW()生成的HANDLE,但是ReadDirectoryChangesW()不接受。它返回 0,并且 GetLastError() 返回“句柄无效。(0x6)”。我在 32 位和 64 位编译下都试过了,以防万一(我使用的是 64 位版本的 Python)。此外,指定的目录似乎并不重要:我指定的所有目录都产生相同的结果,这表明某处的设置有问题。

CreateFileW() 调用中是否有某些东西可能导致 HANDLE 对生成完成端口有效,但会给 ReadDirectoryChangesW() 函数带来胃灼热?

最佳答案

您没有正确初始化 I/O 完成端口,您根本没有初始化 OVERLAPPED 结构。 ReadDirectoryChangesW() 失败,因为 OVERLAPPED::hEvent 字段包含无效的事件对象句柄。这是错误代码所指的无效句柄,而不是目录句柄。

试试这个:

#include "stdafx.h"

#define MAX_BUFFER 4096

struct ThreadData
{
DWORD winerr;
HANDLE handle;
DWORD flags;
BOOL 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 = TRUE;
td.completion_port = NULL;
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();
return 0;
}

td.completion_port = CreateIoCompletionPort(td.handle,
NULL,
(ULONG_PTR)&td,
0); // max num processors
if(td.completion_port == NULL)
{
winerr = GetLastError();
CloseHandle(td.handle);
return 0;
}

ZeroMemory(&td.overlapped, sizeof(td.overlapped)); // <-- add this!

// required if the thread uses GetOverlappedResult()...
// optional if the thread uses GetQueuedCompletionStatus()...
/*
td.overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(td.overlapped.hEvent == NULL)
{
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 == FALSE)
{
winerr = GetLastError();
//CloseHandle(td.overlapped.hEvent);
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.overlapped.hEvent);
CloseHandle(td.completion_port);
CloseHandle(td.handle);

return 0;
}

关于c++ - ReadDirectoryChangesW 拒绝 CreateIoCompletionPort 接受的 HANDLE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40193431/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com