Я добавляю функциональность к моему (Qt-основанному) приложению для мониторинга произвольной папки в моей системе Windows для любой операции рекурсивно (что-то не имеет Qt-вариант QFileSystemWatcher). После открытия папки с помощью CreatFileW(), я создаю порт завершения для получения перекрытого ввода-вывода, а затем я запускаю очередь с использованием ReadDirectoryChangesW().ReadDirectoryChangesW отклонение HANDLE принято CreateIoCompletionPort
Я разместил все это в следующем «простом» консольном приложении 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 («наблюдател»), написанный в C, что обеспечивает функциональность, аналогичную среду Python. Я использовал его в Python, и он работает как ожидалось со всеми теми же настройками в этом фрагменте C++.
В приведенном выше коде, CreateIoCompletionPort() принимает HANDLE, генерируемый CreateFileW(), но ReadDirectoryChangesW() не делает. Он возвращает 0, и GetLastError() возвращает «Ручка недействительна. (0x6)». Я пробовал это под 32- и 64-разрядными компиляторами, на всякий случай это имело какое-либо значение (я использовал 64-битную версию Python). Кроме того, указанный каталог не имеет значения: все указанные мной каталоги приводят к одному и тому же результату, что говорит о том, что проблема связана с настройками где-то.
Есть ли что-то в CreateFileW() вызова, который может привести к HANDLE быть действительным для создания порта завершения, но даст ReadDirectoryChangesW() функцию изжоги?
Ваш 'OVERLAPPED' структура выглядит быть инициализирован. –