ディレクトリのサブファイルが変更されたかどうかを確認する方法
-
09-06-2019 - |
質問
Windows では、フォルダーに変更されたサブファイルがあるかどうかを簡単に判断する方法はありますか?
確認したところ、サブファイルが変更されてもフォルダーの最終変更日は更新されません。
この動作を変更するように設定できるレジストリ エントリはありますか?
大事なことですが、私は NTFS ボリュームを使用しています。
最終的には、この機能を C++ プログラムから実現したいと考えています。
フォルダーが大きすぎるため、ディレクトリ全体を再帰的にスキャンすることはできません。
アップデート:変更が発生している間、プロセスを実行せずにこれを行う方法が本当に必要です。したがって、ファイルシステムウォッチャーをインストールすることは私にとって最適ではありません。
アップデート2:アーカイブ ビットも、最終変更日と同じ問題があるため機能しません。ファイルのアーカイブ ビットは設定されますが、フォルダーは設定されません。
解決
これ 記事 役立つはずです。基本的には、次のような 1 つ以上の通知オブジェクトを作成します。
HANDLE dwChangeHandles[2]; dwChangeHandles[0] = FindFirstChangeNotification( lpDir, // directory to watch FALSE, // do not watch subtree FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes if (dwChangeHandles[0] == INVALID_HANDLE_VALUE) { printf("\n ERROR: FindFirstChangeNotification function failed.\n"); ExitProcess(GetLastError()); } // Watch the subtree for directory creation and deletion. dwChangeHandles[1] = FindFirstChangeNotification( lpDrive, // directory to watch TRUE, // watch the subtree FILE_NOTIFY_CHANGE_DIR_NAME); // watch dir name changes if (dwChangeHandles[1] == INVALID_HANDLE_VALUE) { printf("\n ERROR: FindFirstChangeNotification function failed.\n"); ExitProcess(GetLastError()); }
そして通知を待ちます。
while (TRUE) { // Wait for notification. printf("\nWaiting for notification...\n"); DWORD dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, FALSE, INFINITE); switch (dwWaitStatus) { case WAIT_OBJECT_0: // A file was created, renamed, or deleted in the directory. // Restart the notification. if ( FindNextChangeNotification(dwChangeHandles[0]) == FALSE ) { printf("\n ERROR: FindNextChangeNotification function failed.\n"); ExitProcess(GetLastError()); } break; case WAIT_OBJECT_0 + 1: // Restart the notification. if (FindNextChangeNotification(dwChangeHandles[1]) == FALSE ) { printf("\n ERROR: FindNextChangeNotification function failed.\n"); ExitProcess(GetLastError()); } break; case WAIT_TIMEOUT: // A time-out occurred. This would happen if some value other // than INFINITE is used in the Wait call and no changes occur. // In a single-threaded environment, you might not want an // INFINITE wait. printf("\nNo changes in the time-out period.\n"); break; default: printf("\n ERROR: Unhandled dwWaitStatus.\n"); ExitProcess(GetLastError()); break; } } }
他のヒント
いくつかの優れたサンプルコード このコードプロジェクトの記事
変更が発生したときにプロセスを実行できない場合は、ファイルシステムをスキャンして変更日時を確認する以外にできることはほとんどありません。ただし、これには各ファイルの最後の日付/時刻を保存し、比較する必要があります。
これを高速化するには、 アーカイブビット (ただし、バックアップ ソフトウェアが台無しになる可能性があるため、慎重に作業を行ってください)。
アーカイブビットは、多くのコンピューターファイルシステムに存在するファイル属性、特にFAT、FAT32、およびNTFSです。アーカイブビットの目的は、アーカイブとも呼ばれるバックアップを目的として、ファイルへの増分変更を追跡することです。
アーカイブビットはバイナリビットであるため、1または0のいずれかであるか、この場合、より頻繁にset(1)とclear(0)と呼ばれます。オペレーティングシステムは、ファイルが作成、移動、変更、またはその他の方法で変更されたときに、アーカイブビットを設定します。したがって、アーカイブビットは2つの状態のいずれかを表します。最後のバックアップ以来、「変更」と「変更されていない」。
アーカイブビットは、ファイルを読み取るだけでは影響を受けません。ファイルがコピーされると、元のファイルのアーカイブビットは影響を受けませんが、コピーのアーカイブビットはコピーの作成時に設定されます。
したがって、プロセスは次のようになります。
- すべてのファイルのアーカイブ ビットをクリアします
- ファイルシステムを時間の経過とともに変化させる
- すべてのファイルをスキャンします - アーカイブ ビットが設定されているファイルは変更されています
これにより、プログラムが状態を保持する必要がなくなり、ディレクトリ エントリ (ビットが保存されている場所) を調べるだけでクラスタ化されるため、非常に高速になるはずです。
ただし、変更中にプロセスを実行できる場合は、 ファイルシステムウォッチャー クラス。ここにあります 例 どのように使用するかについて。
にも存在します 。ネット (この種の問題を今後検索する人向け)
おそらく、変更を監視し、後で読み取るためのファイルを作成するプロセスをマシン上で実行したままにしておくことができます。
-アダム
おそらく、説明されているように、DeviceIoControl で NTFS 5 変更ジャーナルを使用できるでしょう。 ここ
.NET の使用に反対しない場合は、 ファイルシステムウォッチャー class はこれを非常に簡単に処理します。
誰かが言及した二重投稿から:WMI イベント シンク
ただし、より良い答えをまだ探しています。
簡単なことはありません - 実行中のアプリがある場合は、他の回答で提案されているように、Win32 ファイル変更通知 API (FindFirstChangeNotification) を使用できます。警告:2000 年頃のトレンド マイクロ リアルタイム ウイルス スキャナは変更をグループ化するため、ファイル システム変更リストを要求するときに非常に大きなバッファを使用する必要がありました。
実行中のアプリがない場合は、NTFS ジャーナリングをオンにして、ジャーナルをスキャンして変更を確認できます。 http://msdn.microsoft.com/en-us/library/aa363798(VS.85).aspx ただし、変更の数がファイルの数よりも大きい場合、ディレクトリ全体をスキャンするよりも遅くなる可能性があります。