ReadDirectoryChangesW не захватывает FILE_ACTION_ADDED при копировании или создании файлов

Я пытаюсь использовать ReadDirectoryChangesW отслеживать, когда файл создается, копируется или перемещается в контролируемый каталог.

Моя проблема в том, что когда я копирую или создаю файл в контролируемом каталоге, событие FILE_ACTION_ADDED не регистрируется ReadDirectoryChangesWвместо этого фиксируются только события FILE_ACTION_MODIFIED.

С другой стороны, когда я перемещаю файл (вместо копирования или создания) из другого каталога в отслеживаемый каталог, создается файл FILE_ACTION_ADDED.

Мне было интересно, если кто-нибудь знает способ заставить ReadDirectoryChangesW захватывать FILE_ACTION_ADDED в 3 моих случаях: создавать, копировать и перемещать.

Я звоню 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

Решение

по факту ReadDirectoryChangesW возвращает буфер, который может содержать более одного FILE_NOTIFY_INFORMATION состав. Первый, как и ожидалось, в начале буфера, но если поле NextEntryOffset не является нулевым, это смещение (в буфере символов) для следующей структуры.

Итак, ваш обратный вызов должен быть:

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);
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]