LAN環境内でサーバの共有フォルダにあるファイルの新規・変更・削除・更新をリアルタイムに取得するとなりますと、フォルダの変更通知APIを使用したほうが良いと思います。
サンプルは下記のとおりです(注意:エラー処理は省いています)。
HANDLE folderHandle = CreateFile(
"\\server\share", // ファイル名へのポインタ
FILE_LIST_DIRECTORY, // アクセス( 読み書き)モード
FILE_SHARE_READ|FILE_SHARE_DELETE, // 共有モード
NULL, // セキュリティ記述子
OPEN_EXISTING, // 作成方法
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // ファイル属性
NULL // コピーするファイルと属性
);
bufferSize = 1024;
FILE_NOTIFY_INFORMATION* buffer= malloc(bufferSize);
while(1)
{
BOOL fResult;
OVERLAPPED overlapped;
overlapped.hEvent=CreateEvent(...);
fResult = ReadDirectoryChangesW(
folderHandle, // 監視するディレクトリのハンドル
buffer, // 読み取った結果を受け取るバッファへのポインタ
bufferSize, // buffer の長さ
FALSE, // ディレクトリまたはディレクトリツリーを監視するためのフラグ(TRUEでも可)
FILE_NOTIFY_CHANGE_FILE_NAME | ... , // 監視に使うフィルタ条件
NULL, // 返されたバイト数
&overlapped, // 重複 I/O 操作に必要な構造体へのポインタ
NULL // 完了ルーチンへのポインタ
);
if(FALSE == fResult) {/* エラー処理 */ break; }
WaitForSingleObject(overlapped.hEvent, ...);
DWORD resultSize;
GetOverlappedResult(folderHandle, &overlapped, &resultSize, FALSE);
// buffer に変更されたファイル名と変更内容が記録されています
// 変更検出後の処理をここに記述します
}
ただ、共有フォルダを対象としたときに変更が検出されるケースとされないケースがあるようです(エクスプローラで共有フォルダの変更が検出できる場合にはこの方法で機能しますが、どのような条件で変更検出が機能しないかはわかりませんでした・・・)。
また、リアルタイム性もそれほど高くありません(変更後数秒かかる場合もあります)。
もし、より正確でリアルタイム性を求めるのでしたら
1. 上記変更検出ルーチンをファイル共有サーバに導入する
2. サーバが変更を検出したらクライアントにデータグラムパケットを送出し、変更検出を通知する。
方法もございます(ここで書いておいて難ですが私はあまり推奨しません・・・)
以上です。
※ #4 で一点間違えがありました、ごめんなさい!この場で修正させてください。
1. の ZwQueryInformationFile() は ZwQueryObject() の間違いでした(ZwQueryInformationFile() ではドライブ名に該当する部分が取得できません)。
プロトタイプは
ypedef enum _OBJECT_INFORMATION_CLASS{
ObjectBasicInformation,
ObjectNameInformation,
ObjectTypeInformation,
ObjectAllInformation,
ObjectDataInformation
} OBJECT_INFORMATION_CLASS;
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING ObjectName;
} OBJECT_NAME_INFORMATION;
NTSYSAPI NTSTATUS NTAPI ZwQueryObject(
IN HANDLE ObjectHandle OPTIONAL, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG Length, OUT PULONG ResultLength );
で、
OBJECT_NAME_INFORMATION* NameInfo;
ULONG ResultLength;
NTSTATUS status = ZwQueryObject(FileHandle, ObjectNameInformation, NameInfo, NameInfoSize, &ResultLength);
のように使います。
お礼
回答ありがとうございます。参考にします。 LAN環境(Windowsのワークグループ環境)内でサーバの共有フォルダにあるファイル の新規・変更・削除・更新をリアルタイムに取得できないか?考えていました。 まず、サーバ管理者がサーバ上にあるファイルを操作した場合の情報取得をどうすれば? これはmacchunさんから回答していただいたAPIを参考にテストしてみます。 問題はクライアントからサーバ上の共有フォルダにあるファイルを新規・変更・削除・更新 を行った場合の情報をリアルタイムに取得できないかを今でも考えています。 Windowsネットワーク関係のAPIを使ってテストをしてみましたが、リアルタイムに情報を 取得できませんでした。NetSessionEnum、NetFileEnumなど(Net系のAPI)リアルタイム には使えないAPIでした。Winsock2で対応できるかなと?調べましたがダメでした。 できないはずはないのでこれからも調べてみます。 macchunさん、アドバイスありがとうございます。