8

FileSystemWatcher を使用して、ファイルがいつ変更または削除されたかを確認していますが、ファイルが別のアプリケーションによっていつ読み取られたかを確認する方法があるかどうか疑問に思っています。

例: ハードドライブにファイル C:\test.txt があり、FileSystemWatcher を使用して監視しています。別のプログラム (私の制御下にない) がそのファイルを読み取ります。そのイベントをキャッチし、可能であれば、ファイルを読み取っているプログラムを確認し、それに応じてファイルの内容を変更したいと思います。

4

6 に答える 6

4

ログファイルが外部から読み取られたときにログファイルに書き込みたい、またはその効果があるように思えます。その場合、NotifyFilters 値 LastAccess があります。これが FileSystemWatcher.NotifyFilter プロパティのフラグの 1 つとして設定されていることを確認してください。最終アクセス時刻が変更されると、FileSystemWatcher で Changed イベントが発生します。

現在、FileSystemWatcher では、読み取りと変更を直接区別することはできません。どちらも、LastAccess への「変更」に基づいて Changed イベントを発生させます。したがって、多数のファイルへの読み取りを監視することは不可能です。ただし、監視しているファイルはわかっているようです。そのため、そのファイルの FileInfo オブジェクトがあり、FileSystemWatcher がその Changed イベントを発生させた場合、新しいオブジェクトを取得して LastAccessTime 値を比較できます。アクセス時刻が変更され、LastWriteTime が変更されなかった場合、ファイルは読み取られているだけです。

簡単に言えば、読み取り中にファイルに加えた変更は、他のアプリにすぐには表示されず、「最初にそこに到達」してファイルをロックして書き込むこともできません。彼らがそれを見る前に。そのため、FileSystemWatcher を使用して読み取り要求を「傍受」し、そのアプリに表示させたいコンテンツを表示することはできません。別のアプリケーションのユーザーがあなたが書いたものを見ることができる唯一の方法は、アプリケーションもファイルを見ていて、ファイルを再ロードする場合です。これにより、別の Changed イベントが発生し、他のアプリケーションがファイルをリロードし続ける限り、無限ループが発生します。

また、読み取りと書き込みの Changed イベントも取得します。テキスト エディターでファイルを開き (実質的には何でも構いません)、変更を加えてから保存すると、最終アクセス時刻の変更を探している場合、2 つの Changed イベントが発生します。ファイルがエディターによって開かれると、最初のものはオフになります。その時点では、書き込みが発生するかどうかわからない可能性があるため、ファイルへの純粋な読み取り専用アクセスを探している場合は、SOL です。

于 2010-09-01T20:37:35.497 に答える
2

これを行う最も簡単な方法は、タイマー (System.Threading.Timer) を使用することです。そのコールバックは、最後の

System.IO.File.GetLastAccessTime(path)

のようなもの(おそらくもう少しロックがかかります...)

public class FileAccessWatcher
{

public Dictionary<string, DateTime> _trackedFiles = new Dictionary<string, DateTime>();

private Timer _timer;

public event EventHandler<EventArgs<string>> FileAccessed = delegate { };

public FileAccessWatcher()
{
    _timer = new Timer(OnTimerTick, null, 500, Timeout.Infinite);
}

public void Watch(string path)
{
    _trackedFiles[path] = File.GetLastAccessTime(path);
}

public void OnTimerTick(object state)
{
    foreach (var pair in _trackedFiles.ToList())
    {
        var accessed = File.GetLastAccessTime(pair.Key);
        if (pair.Value != accessed)
        {
            _trackedFiles[pair.Key] = accessed;
            FileAccessed(this, new EventArgs<string>(pair.Key));
        }
    }

    _timer.Change(500, Timeout.Infinite);
}
}
于 2010-09-01T20:13:08.440 に答える
2

SysInternals のプログラム FileMon があります... システム内のすべてのファイル アクセスを追跡できます。そのソースを見つけ、それが使用する win32 フックを理解できれば、それらの関数を C# でマーシャリングして、必要なものを取得できます。

于 2010-09-01T20:16:32.060 に答える
1

ポーリング ループで FileInfo.LastAccessTime と FileInfo.Refresh() を使用できます。

http://msdn.microsoft.com/en-us/library/system.io.fileinfo_members.aspx

于 2010-09-01T20:09:15.427 に答える
0

はい、ファイル システム フィルター ドライバーを使用すると、すべての読み取り要求をキャッチして分析し、読み取られているデータを置き換えることさえできます。このようなドライバーを自分で開発することは可能ですが、非常に時間がかかり複雑です。CallbackFilterという製品を提供しています。これには、すぐに使用できるドライバーが含まれており、ユーザー モードでフィルタリング ビジネス ロジックを実装できます。

于 2010-09-02T09:33:16.683 に答える
-2

別のプロセスがロックされていることを検出するのに役立つ小さなスニペット:

 static bool IsFileUsedbyAnotherProcess(string filename) 
        { 
            try 
            { 
                using(var file = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
                {
                }
            } 
            catch (System.IO.IOException exp) 
            { 
                return true; 
            } 
            return false; 
        }
于 2010-09-01T20:04:33.850 に答える