1

I'm trying to build a small program to monitor my pfirewall.log, but I can't seem to open it. I found quite many (simple) answers, that all kinda say

// use FilesystemWatcher
// open FileStream
// read from last position to end
// output new lines

The problem here is: The file seems to always be opened by another process already. I guess that's the windows process writing to the file, since it's getting written to all the time, as Notepad++ shows me.

Which means, Notepad++ can for some reason do what I can not: Read the file despite it being opened already.

I initialize my monitor in the constructor:

    public FirewallLogMonitor(string path)
    {
        if (!File.Exists(path))
            throw new FileNotFoundException("Logfile not found");

        this.file = path;
        this.lastPosition = 0;
        this.monitor = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path));
        this.monitor.NotifyFilter = NotifyFilters.Size;

    }

And try to read the file on monitor.Changed event:

    private void LogFileChanged(object sender, FileSystemEventArgs e)
    {
        using (FileStream stream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
        using (StreamReader reader = new StreamReader(stream))
        {
            stream.Seek(this.lastPosition, SeekOrigin.Begin);
            var newLines = reader.ReadToEnd();
            this.lastPosition = stream.Length;
            var filteredLines = filterLines(newLines);
            if (filteredLines.Count > 0)
                NewLinesAvailable(this, filteredLines);
        }
    }

It always throws the IOException on new FileStream(...) to tell me the file is already in use.

Since Notepad++ does it, there has to be a way I can do it too, right?

**Edit: ** A button does this:

    public void StartLogging()
    {
        this.IsRunning = true;
        this.monitor.Changed += LogFileChanged;
        this.monitor.EnableRaisingEvents = true;
    }

**Edit2: ** This is not a duplicate of FileMode and FileAccess and IOException: The process cannot access the file 'filename' because it is being used by another process, since that one assumes I have control over the writing process. Will try the other suggestions, and report back with results.

Community
  • 1
  • 1
Squirrelkiller
  • 1,557
  • 1
  • 15
  • 29
  • 4
    `FileShare.Read` means "allows subsequent opening of the file for reading". If the file is already opened for writing, this will not work. Use `FileShare.ReadWrite | FileShare.Delete` to be maximally permissive of what other users may do with the file. – Jeroen Mostert Jan 03 '17 at 16:13
  • [What's the least invasive way to read a locked file in C# (perhaps in unsafe mode)?](http://stackoverflow.com/q/3560651/669576) – Johnny Mopp Jan 03 '17 at 16:13
  • 2
    Note that after you fix the `FileShare` to fix your exception, you will randomly get exceptions on `var newLines = reader.ReadToEnd()` when the other process that owns the file locks it to write a new log line. This will be *intermittent* and depends on when Windows needs to write to the file, meaning you could go weeks before you ever see the exception. You need a `try/catch` and a way to recover from a failed read. – Quantic Jan 03 '17 at 16:18
  • Also note that `StreamReader` does not allow seeking because of its internal buffer, but you can work around it as shown [here](http://stackoverflow.com/questions/5404267/streamreader-and-seeking). Your `this.lastPosition` is the position from StreamReaders internal buffer, not the "actual" position at the end of the last line you read. This may be irrelevant since you are using `reader.ReadToEnd()` instead of `reader.ReadLine()`, but it's something you need to be aware of. – Quantic Jan 03 '17 at 16:20
  • Possible duplicate of [FileMode and FileAccess and IOException: The process cannot access the file 'filename' because it is being used by another process](http://stackoverflow.com/questions/18343079/filemode-and-fileaccess-and-ioexception-the-process-cannot-access-the-file-fil) – Class Skeleton Jan 03 '17 at 16:21
  • I marked this questions as a possible duplicate based on the status of "application B" in the linked question. The fix is essentially what is covered in the first comment here - use `FileShare.ReadWrite`. – Class Skeleton Jan 04 '17 at 13:28
  • you're right, the ReadWrite permission fixed it. Still, IMO it's not a duplicate, since that other question is based on having control of the writing application, which led me the thought that windows wouldn't actually grant me that permission. @Jeroen Mostert, if you make your comment an answer I'll mark it as solution. – Squirrelkiller Jan 04 '17 at 13:39

1 Answers1

0

If i understand your question you can use the notepad++ itself with a plugin to monitor you need to go to:

plugins -> Document Moniter -> Start to monitor

if you dont have this plugin you can download it here:

http://sourceforge.net/projects/npp-plugins/files/DocMonitor/

Moshe D
  • 728
  • 1
  • 4
  • 13
  • 1
    This doesn't help me, since I process the data before showing it. Edit: Also, using notepad++ itself doesn't make me learn how to do it right. – Squirrelkiller Jan 03 '17 at 17:22