我尝试使用ReadDirectoryChangesW
来跟踪文件创建,复制或移动到受监控目录的时间。
我的问题是,当我在受监控目录上复制或创建文件时,ReadDirectoryChangesW
没有捕获FILE_ACTION_ADDED事件,而是仅捕获FILE_ACTION_MODIFIED事件。
另一方面,当我将文件(而不是复制或创建)从另一个目录移动到受监控目录时,会捕获一个FILE_ACTION_ADDED。
我想知道是否有人知道如何让ReadDirectoryChangesW在我的3个案例中捕获FILE_ACTION_ADDED:创建,复制和移动。
我这样打电话给ReadDirectoryChangesW
:
ReadDirectoryChangesW(directory_handle, buffer, MAX_EVENTs_BUFFER,
FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE,
NULL, (LPOVERLAPPED)usr_data, FileIOCompletionRoutine)
我使用CreateFileA
初始化directory_handle
:
CreateFileA(directory_path.c_str(),
FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE |
FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS |
FILE_FLAG_OVERLAPPED, NULL);
然后,在我的FileIOCompletionRoutine
上,当我将文件复制到受监控目录时,或者当我创建文件时,我只会在移动文件时从未收到FILE_ACTION_ADDED。这是正常行为还是我做错了什么?
编辑1:
VOID CALLBACK FileIOCompletionRoutine(_In_ DWORD err, _In_ DWORD bytes, _Inout_ LPOVERLAPPED lpOverlapped)
{
CUSTOM_OVERLAPPED* pCustomOverlapped = (CUSTOM_OVERLAPPED*)lpOverlapped;
char* buffer_offset = (char*)pCustomOverlapped->buffer;
PFILE_NOTIFY_INFORMATION pInfo = (PFILE_NOTIFY_INFORMATION)buffer_offset;
do
{
pInfo = (PFILE_NOTIFY_INFORMATION)buffer_offset;
switch (pInfo->Action)
{
case FILE_ACTION_ADDED:
{
std::cout << "file added!\n";
break;
}
case FILE_ACTION_MODIFIED:
{
std::cout << "file modified!\n";
break;
}
// and so on...
}
buffer_offset += pInfo->NextEntryOffset;
} while(pInfo->NextEntryOffset);
}
编辑2:
我发现,如果我从FILE_NOTIFY_CHANGE_LAST_WRITE
中移除ReadDirectoryChangesW
,则在创建新文件时以及当我执行剪切和粘贴时正确捕获FILE_ACTION_ADDED
事件,但不是我会复制并粘贴,在这种情况下它会触发FILE_ACTION_MODIFIED
。为了在复制并粘贴到受监控目录时获得FILE_ACTION_ADDED
,我还需要删除FILE_NOTIFY_CHANGE_SIZE
标记。
因此,如果想要在受监视目录中跟踪新文件(创建,复制或移动),我只需要FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME
函数上的标记ReadDirectoryChangesW
。
如果我想跟踪已修改的(已存在于目录中)文件,我需要FILE_NOTIFY_CHANGE_SIZE
,但我不能使用ReadDirectoryChangesW
中的三个标记来跟踪新文件和修改过的文件。
您是否有人找到了使用逻辑或三个标志跟踪所有这些事件的方法,还是我必须为每个案例调用ReadDirectoryChangesW
不同的标志?
答案 0 :(得分:1)
实际上ReadDirectoryChangesW
返回一个可以包含多个FILE_NOTIFY_INFORMATION
结构的缓冲区。第一个在缓冲区的开头是预期的,但如果字段NextEntryOffset
不为null,则它是下一个结构的偏移量(在char缓冲区中)。
所以你的回调应该是:
VOID CALLBACK FileIOCompletionRoutine(_In_ DWORD err, _In_ DWORD bytes, _Inout_ LPOVERLAPPED lpOverlapped)
{
CUSTOM_OVERLAPPED* pCustomOverlapped = (CUSTOM_OVERLAPPED*)lpOverlapped;
char* buffer_offset = (char*)pCustomOverlapped->buffer;
PFILE_NOTIFY_INFORMATION pInfo = (PFILE_NOTIFY_INFORMATION)buffer_offset;
do {
switch (pInfo->Action)
{
case FILE_ACTION_ADDED:
{
std::cout << "file added!\n";
break;
}
case FILE_ACTION_MODIFIED:
{
std::cout << "file modified!\n";
break;
}
// and so on...
}
pInfo = (PFILE_NOTIFY_INFORMATION)(buffer_offset + pInfo->NextEntryOffset);
} while (0 != pInfo->NextEntryOffset);
}