Question

My scenario is as follows:

I have 1 program that logs its actions to a txt file continuously while it is running. It never closes the file while it is running. I cannot modify this program.

I want to monitor this file with my other application (written in VB.NET VS 2005). My problem is that it appears that data being written to this log doesn't register immediately.

I've tried using a FileSystemWatch to watch the file for updates. The problem with this approach is that I don't get notified immediately of data being written. Manually browsing to the folder with explorer and then sorting it triggers the changed event though (don't ask me why). I would probably also get notified if the file was closed by the other app.

I've also tried just polling the file and reading its last write date. This definitely only works if the file is being closed after every write.

Is there any way to accomplish this monitoring without having the application writing to the log close the file and reopen it or manually access the folder being written.

Here is my code for the file watch:

    If IO.File.Exists(recorder_path) Then
        Dim recorder_dir As String = recorder_path.Remove(recorder_path.LastIndexOf("\"))
        Dim recorder_name As String = recorder_path.Substring(recorder_path.LastIndexOf("\") + 1)

        recorder_watcher = New System.IO.FileSystemWatcher()
        recorder_watcher.Path = recorder_dir
        recorder_watcher.Filter = recorder_name
        recorder_watcher.NotifyFilter = NotifyFilters.Size
        AddHandler recorder_watcher.Changed, AddressOf recorder_update
        recorder_watcher.EnableRaisingEvents = True
    End If

    Private Sub recorder_update(ByVal source As Object, ByVal event_args As System.IO.FileSystemEventArgs)
        'Do Stuff
    End Sub

I'm running this app on W7 and XP and only accessing local folders.

UPDATE, Another approach:

The below code seems to work quickly enough:

    Dim new_txt As String = ""

    Dim fs As New FileStream(recorder_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
    Dim file_reader = New StreamReader(fs)
    file_reader.ReadToEnd()

    While 1
        new_txt = ""
        System.Threading.Thread.Sleep(5)
        System.Windows.Forms.Application.DoEvents()

        new_txt += file_reader.ReadToEnd().ToUpper()
        If (new_txt.Length > 0)
           'Do stuff w/new txt
        End If
    End While

This appears to give me updates every time the logging process writes to the file.

Thanks,

Ian

Was it helpful?

Solution

Indeed FileSystemWatcher won't give you much and reading the file periodically would help, but only if the file is opened with share mode that allows other processes to read the file.

An alternative is to use a filesystem filter driver which catches all write operations immediately. This will work if the driver is installed on the same system where the file is located (i.e. filter can't work on remote disks).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top