Windowsシステム上の任意のフォルダをの任意のアクティビティを再帰的に監視する機能をQtベースのアプリケーションに追加しています(Qtの変更QFileSystemWatcherにはありません)。 CreatFileW()でフォルダを開いた後、重複したI/Oを受け取る完了ポートを作成してから、ReadDirectoryChangesW()を使用して読み込みをキューに入れます。ReadDirectoryChangesW 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++フラグメントのすべての同じ設定で期待どおりに動作します。はCreateFileW(によって生成されたハンドルを受け入れる
上記のコードで、CreateIoCompletionPort())が、ReadDirectoryChangesW()はありません。 0を返し、GetLastError()が "ハンドルが無効です(0x6)"を返します。私は32ビットと64ビットの両方のコンパイルのもとでこれを試しました。ちょっとした違いがあった場合に備えて(私は64ビット版のPythonを使っていました)。また、指定されたディレクトリは重要ではありません。私が指定したすべてのディレクトリは同じ結果を生成します。これは設定のどこかに問題があることを示しています。
HANDLEが完了ポートを生成するために有効であることが原因かもしれませんが、ReadDirectoryChangesWを(与えるだろうCreateFileW()コール)関数胸焼けで何かはありますか?
あなた 'OVERLAPPED'構造は初期化されていないことになりそうです。 –