18

ReadDirectoryChangesWいくつかのディレクトリのコンテンツの変更 (ファイルの上書き、ファイルの削除、名前の変更など) について効果的に通知できるように、機能を理解しようとしています。

私の最近の観察の 1 つは、すべてのファイル書き込み操作に対して、単一のファイルに対して常に 2 つの通知を受け取ることです。

私はそれを非常に注意深く追跡しましたが、ファイルを上書きすると(たとえば、新しいコンテンツを含む.txtファイル-基本的に余分な文字がいくつか含まれています)、ReadDirectoryChangesW()そのファイルの保存ごとに2回通知されると確信しています.

変更ごとに一度だけ通知されることを期待しているので、これは深刻なことです。アプリケーションで 1 回だけ実行する必要がある操作を意図せずに繰り返したくありません。

この動作は既知ですか? 1 回の変更につき 1 回だけ通知を受け取る方法はありますか? 二重通知を効果的に回避する方法はありますか?

私が使う:

  • アンマネージ C++
  • ビジュアル スタジオ 2012
  • ウィンドウズ 7 x64

私は非常に基本的なコードを使用してテストを行っていますが、見たいと思うので、ここに示します。

HANDLE hDir = CreateFile(
    lpDir,
    FILE_LIST_DIRECTORY,
    FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
    NULL, 
    OPEN_EXISTING, 
    FILE_FLAG_BACKUP_SEMANTICS, 
    NULL);

    int nCounter = 0;
    FILE_NOTIFY_INFORMATION strFileNotifyInfo[1024];
    DWORD dwBytesReturned = 0;   

    while(TRUE)
    {
        if( ReadDirectoryChangesW ( hDir, (LPVOID)&strFileNotifyInfo, sizeof(strFileNotifyInfo), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytesReturned, NULL, NULL) == 0)
        {
            ErrorCheck(_T("Reading Directory Change"));
        }
        else
        {
            _tcout << _T("File Modified: ") << strFileNotifyInfo[0].FileName << endl;
            _tcout << _T("Loop: ") << nCounter++ << endl;
        }
    }
4

2 に答える 2

27

ReadDirectoryChangesW() のファイル システムの見方は非常に近視眼的です。ファイルシステムへのすべての変更を確認し、忠実に報告します。はい、ファイルに書き込むときは複数あることがよくあります。これは、使用している特定のファイル システムの実装の詳細ですが、Windows で一般的なものは、ファイルのメタデータを格納するファイルのディレクトリ エントリも保持します。

したがって、ファイル データの書き込みが表示されます。しかし、ディレクトリ エントリが変更されていることわかります。特にファイル サイズは、ファイルを書き込んだり、ファイルにデータを追加したりすると変化する可能性があります。また、ディレクトリ エントリに記録された最終書き込みおよび最終アクセスのタイムスタンプ。それ以外の場合、API は行われる変更の種類を認識できず、低レベルの書き込みのみを認識します。また、特定のプロセスが書き込みを要求したこともまったく認識していません。

これはあなたが対処しなければならないものです。これらの書き込みを区別する方法はありません。あなたが知っているのは「ファイルが変更された」ということだけです。どのように、なぜ、誰が、どのくらいの頻度で、完全に発見することはできません。

他に対処しなければならないことは、通知が生成された時点で、ファイルを書き込むプロセスがまだファイルをロックしている可能性が非常に高いということです。これにより、ファイルを自分で使用して何か有用なことを行うことができなくなります。ファイルの読み取りやコピーと同様に、失敗する可能性があります。プロセスがファイルで完了し、ファイルへのハンドルが閉じられるまで待つ必要があります。自分でファイルを開いて共有を拒否する以外に、これを発見する方法はありません。これにはタイマーが必要で、定期的に自分でファイルのロックを取得しようとします。配管が整ったら、ファイルの複数の変更通知を受け取ることはもはや問題ではありません。

于 2012-12-26T13:03:40.070 に答える
9

これは、メモ帳にファイルを保存した後、procmon のログを同時に実行したコードの結果操作です。ReadDirectoryChangesW() からの 2 つの通知と、procmon からの 2 つの通知があります。2 IRP_MJ_WRITE メモ帳から 1 つ (WriteFile) システム キャッシュ マネージャーから 1 つ (CcWriteBehind) プロモン

于 2012-12-26T06:40:32.353 に答える