2010-11-16 18 views
1

J'ai un fichier journal qui est écrit par une application tierce et je voudrais que mon application "lise" ce fichier journal en temps réel/proche, analyse le nouveau journal entrées et agir sur certains événements.Utiliser MemoryMappedFile et FileSystemWatcher pour détecter de nouvelles entrées dans le fichier journal

Ma pensée était que je pourrais réaliser ceci avec une combinaison de FileSystemWatcher (pour signaler des changements de dossier) et de MemoryMappedFile (pour continuer la lecture d'un certain décalage). Cependant, comme c'est la première fois que j'utilise MemoryMappedFiles, je rencontre des problèmes qui découlent probablement du fait que je ne comprends pas bien le concept (par exemple, je ne peux pas ouvrir le fichier existant tel qu'il est utilisé par les autres processus).

Je me demandais si quelqu'un avait un exemple de comment utiliser MemoryMappedFiles pour lire un fichier qui est verrouillé par un autre processus?

Merci,

Tom

EDIT:

D'après les commentaires, il semble que la mémoire mappée fichiers ne me aider à accéder à des fichiers qui ont un verrou exclusif. Cependant, des outils "en queue" comme, par ex. Baretail (http://www.baremetalsoft.com/baretail/index.php) est capable de faire exactement cela. Il n'a aucun problème à lire le fichier qui a un verrou exclusif d'une autre application à intervalles de 1s). Donc, il doit y avoir un moyen de faire cela?

editEdit:

Pour répondre à ma propre question, l'affaire dans l'ouverture d'un fichier verrouillé est, en créant le FileStream avec les drapeaux d'accès suivants:

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

J'ai fait un commentaire à propos de l'argument FileShare requis dans le poste de James. Un MMF ne peut pas contourner un fichier complètement verrouillé, vous seriez bloqué si c'est le cas. –

+0

S'il vous plaît voir mon Modifier ci-dessus. Le problème semble être plus concentré sur le verrouillage exclusif que MMF vs FileStream maintenant.J'ai essayé plusieurs outils de queue Windows et ils semblent tous être en mesure de contourner la serrure exclusive très bien, aucune idée de comment ils y parviennent? – TJF

Répondre

1

Pour répondre à ma propre question, l'astuce dans la lecture d'un fichier verrouillé crée le FileStream avec les drapeaux d'accès suivants:

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

Maintenant il est juste une question de l'un intervalle faisant fonction sondages ou à la recherche d'événements de changement FileSystemWatcher pour détecter le fichier change

+0

Avez-vous utilisé MemoryMappedFile? Je cherche à mettre en œuvre la même chose. – Devela

0

[Begin 2ème EDIT]

Une autre idée ...

Si l'application tierce utilise un framework de journalisation tel que NLog, l og4net, ou System.Diagnostics, vous pouvez toujours écrire votre propre Target/Appender/TraceListener et acheminer les messages quelque part que vous pourriez les regarder (comme un fichier qui n'est pas ouvert exclusivement, à un autre processus, etc.).

Si votre application tierce utilise un cadre de l'exploitation forestière, nous aurions probablement entendu parler maintenant ;-)

[Fin 2e EDIT]

[Begin EDIT]

Je pense J'ai mal lu la question. Cela a semblé d'abord comme si vous utilisiez une bibliothèque tierce pour laquelle la journalisation était implémentée et que vous vouliez effectuer cette analyse à partir du programme qui générait la journalisation. Après avoir relu votre question, il semble que vous vouliez "écouter" le fichier journal depuis l'extérieur de l'application. Si c'est le cas, ma réponse ne vous aidera probablement pas. Pardon.

[Fin EDIT]

Je n'ai rien à offrir au sujet MemoryMappedFiles, mais je me demande si vous pouvez réaliser ce que vous êtes après en écrivant un écouteur personnalisé/target/appender pour le système d'exploitation forestière 3ème partie?Par exemple, si vous utilisez NLog, vous pouvez écrire une cible personnalisée et y diriger tous vos messages de journalisation (tout en les dirigeant vers la ou les «vraies» cibles). De cette façon, vous obtenez crack à chaque message de journal comme il est connecté (donc c'est en fait en temps réel, pas près de temps réel). Vous pourriez faire la même chose avec log4net et System.Diagnostics.

Notez que NLog a même une cible "MethodCall". Pour utiliser celui-là, il suffit d'écrire une méthode statique avec la bonne signature. Je ne sais pas si log4net a un concept similaire à celui-ci. Il semble qu'il soit plus facile de travailler de façon fiable que d'essayer de lire et d'analyser le fichier journal tel qu'il est écrit par le logiciel tiers.

0

Je ne suis pas sûr si MemoryMappedFiles va vous aider. Jetez un oeil à FileStream:

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

Bien que si l'application 3ème partie a le fichier verrouillé exclusivement, il n'y a pas grand-chose que vous pouvez faire à ce sujet ...

+0

Eh bien, avec FileStream, je ne peux pas lire les fichiers qui sont verrouillés exclusivement par un autre processus et j'espérais pouvoir y parvenir avec Memory Mapped Files. Windows queue outils comme Baretail (http://www.baremetalsoft.com/baretail/index.php) sont capables de lire les fichiers verrouillés juste bien, donc il doit y avoir un moyen d'atteindre ce – TJF

+1

FileShare.Read ne va pas pour fonctionner, l'application qui écrit le fichier journal a déjà obtenu un accès en écriture. Vous ne pouvez pas nier un droit déjà acquis. Probablement aussi le problème du PO. Vous * devez * spécifier ReadWrite ici. –

0

Si le fichier est « utilisé » , il n'y a rien à faire à ce sujet. C'est vraiment "en usage". MemoryMappedFiles permet de lire de grandes quantités de données sur le disque ou de partager des données avec d'autres programmes. Cela ne vous aidera pas à contourner la limitation "en cours d'utilisation".

0

fichiers Memorymapped sont dans les mêmes restrictions que le FileStream vous initialisez avec, assurez-vous que vous initialisez votre mémoire-mappée-fichier comme celui-ci

var readerStream = new FileStream (chemin, FileMode.Open, FileAccess. Lire, FileShare.ReadWrite);

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

Si d'autres processus l'ont complètement verrouillé, même si vous avez mal écrit, vous ne savez pas s'il y a un moyen de contourner cela. Peut-être utiliser une minuterie détecter quand le processus a cessé d'écrire.

0

J'ai fait quelque chose de similaire juste pour surveiller les fichiers journaux sur une console (par opposition au traitement), mais les principes sont les mêmes. Comme vous, j'utiliser un FileSystemWatcher, et la logique importante est dans mon gestionnaire d'événements 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; 
} 

où lastPositions est

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

et DumpNewData est tout simplement

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); 
} 
+0

malheureusement, cela ne concerne pas la lecture de fichiers avec un verrouillage exclusif si – TJF