1

サード パーティ製アプリケーションによって書き込まれたログ ファイルがあり、そのアプリケーションでそのログ ファイルをリアルタイムまたはニア タイムで「読み取り」、新しいログ エントリを解析し、特定のイベントに対応させたいと考えています。

私の考えでは、FileSystemWatcher (ファイルの変更を知らせる) と MemoryMappedFile (特定のオフセットからの読み取りを続行する) の組み合わせでこれを達成できると考えていました。

ただし、MemoryMappedFiles を使用するのはこれが初めてなので、概念を正しく理解していないために発生する可能性があるいくつかの問題に遭遇します (たとえば、他のプロセスで使用されている既存のファイルを開くことができません)。

誰かが MemoryMappedFiles を使用して別のプロセスによってロックされているファイルを読み取る方法の例を持っているかどうか疑問に思っていましたか?

ありがとう、

トム

編集:

コメントから、メモリ マップ ファイルは、排他ロックを持つファイルへのアクセスに役立たないようです。ただし、Baretail (http://www.baremetalsoft.com/baretail/index.php) などの「テール」ツールは、まさにそれを行うことができます。1秒間隔で別のアプリケーションから排他ロックを持つファイルを読み取るのに問題はありません)。それで、これを行うには何らかの方法が必要ですか?

編集編集:

私自身の質問に答えるために、ロックされたファイルを開く際の秘訣は、次のアクセス フラグを使用して FileStream を作成することです。

fileStream = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite);
4

6 に答える 6

2

私自身の質問に答えるために、ロックされたファイルを読み取る際の秘訣は、次のアクセス フラグを使用して FileStream を作成することです。

FileStream fileStream = new System.IO.FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.ReadWrite);

間隔ベースのポーリングを実行するか、FileSystemWatcher 変更イベントを検索してファイルの変更を検出するだけです。

于 2010-11-16T21:47:24.630 に答える
0

メモリマップトファイルは、初期化するFileStreamと同じ制限を受けます。必ず、このようにメモリマップトファイルを初期化してください。

var readerStream = new FileStream(path、FileMode.Open、FileAccess.Read、FileShare.ReadWrite);

var mmf = MemoryMappedFile.CreateFromFile(readerStream、null、0、MemoryMappedFileAccess.Read、null、HandleInheritability.None、false);

他のプロセスが書き込みからも完全にロックしている場合は、運が悪いので、それを回避する方法があるかどうかはわかりません。おそらく、プロセスが書き込みを停止したことを検出するタイマーを使用します。

于 2010-11-16T21:22:29.607 に答える
0

(処理ではなく)コンソールでログファイルを監視するためだけに似たようなことをしましたが、原則は同じです。あなたと同じように、私はFileSystemWatcherを使用しており、重要なロジックはOnChangedイベントハンドラーにあります。

case WatcherChangeTypes.Changed:
{
    System.IO.FileInfo fi = new FileInfo(e.FullPath);

    long prevLength;

    if (lastPositions.TryGetValue(e.FullPath, out prevLength))
    {
        using (System.IO.FileStream fs = new FileStream(
           e.FullPath, FileMode.Open, FileAccess.Read))
        {
            fs.Seek(prevLength, SeekOrigin.Begin);
            DumpNewData(fs, (int)(fi.Length - prevLength));
            lastPositions[e.FullPath] = fs.Position;
        }
    }
    else
      lastPositions.Add(e.FullPath, fi.Length);

    break;
}

lastPositionsは

Dictionary<string, Int64> lastPositions = new Dictionary<string, long>();

DumpNewDataは単純です

private static void DumpNewData(FileStream fs, int bytesToRead)
{
    byte[] bytesRead = new byte[bytesToRead];
    fs.Read(bytesRead, 0, bytesToRead);
    string s = System.Text.ASCIIEncoding.ASCII.GetString(bytesRead);
    Console.Write(s);
}
于 2010-11-16T21:23:13.273 に答える
0

MemoryMappedFilesが役立つかどうかはわかりません。FileStreamを見てください:

var stream = new FileStream(path, FileMode.Open, FileShare.Read);
stream.Seek(offset, SeekOrigin.Begin);

サードパーティのアプリケーションでファイルが排他的にロックされている場合でも、それについてできることはあまりありません...

于 2010-11-16T20:50:15.647 に答える
0

ファイルが「使用中」の場合、それについてできることは何もありません。まさに「使用中」です。MemoryMappedFiles は、ドライブから大量のデータを読み取るか、他のプログラムとデータを共有するためのものです。「使用中」の制限を回避するのには役立ちません。

于 2010-11-16T21:06:48.050 に答える
0

[2回目の編集開始]

もう一つのアイデア...

サード パーティのアプリが NLog、log4net、または System.Diagnostics などのロギング フレームワークを使用している場合でも、独自の Target/Appender/TraceListener を記述して、メッセージを表示できる場所 (たとえば、排他的に開かれていない、別のプロセスなど)。

サードパーティのアプリがロギング フレームワークを使用している場合は、おそらく今までに聞いたことがあるでしょう ;-)

[2回目の編集を終了]

[編集開始]

私は質問を読み違えたと思います。最初は、ロギングが実装されているサードパーティのライブラリを使用しているように聞こえましたが、ロギングを生成していたプログラム内からこの解析を行いたいと考えていました。質問を読み直すと、アプリケーションの外部からログ ファイルを「聞きたい」ように思えます。その場合、私の答えはおそらく役に立たないでしょう。ごめん。

[編集終了]

MemoryMappedFiles について提供できるものは何もありませんが、サード パーティのログ システム用のカスタム リスナー/ターゲット/アペンダーを作成することで、目的を達成できるのではないでしょうか?

たとえば、NLog を使用している場合は、カスタム ターゲットを作成し、すべてのログ メッセージをそこに送信することができます (「実際の」ターゲットにも送信します)。このようにして、ログに記録されるたびに各ログメッセージにクラックが発生します(したがって、実際にはリアルタイムであり、ほぼリアルタイムではありません)。log4net と System.Diagnostics でも同じことができます。

NLog には「MethodCall」ターゲットさえあることに注意してください。それを使用するには、正しい署名で静的メソッドを記述するだけです。log4net にこれと同様の概念があるかどうかはわかりません。

これは、サードパーティのソフトウェアによって書き込まれているログ ファイルを読み取って解析するよりも、確実に動作するようにする方が簡単なようです。

于 2010-11-16T20:48:18.750 に答える