2

Question:

Is it posible to detect when a file, for wich a have an open FileStream, was renamed.

Case:

I am trying to monitor the logs for our application, I read from the logfiles since I do not want to interfere with the logging itself.

This works great until the file gets rolled. My application keeps reading from a renamed file without even noticing.

I tried using a FileSystemWatcher to detect the roll, but sometimes a get a lot of events, sometimes I don't, so that's not really a good solution (also the logfiles could reside on a network share wich could be an extra hold-back for using a FSW).

If I could find out which file(name) I have an open handle to, I could compare that to the _fileName but I don't know how or if this can be done.

Are there any other options I could explore?

Code:

this is a simplified version of my filemonitoring class:

public class MonitorFile
{
    private String _fileName = String.Empty;
    private bool _stopMonitoring = false;

    public MonitorFile(string fileName)
    {
        _fileName = fileName;
    }

    // Simplified method
    public void StartMonitoring()
    {
        using (var reader = new StreamReader(
                    new FileStream(
                        _monitorFileName,
                        FileMode.Open,
                        FileAccess.Read,
                        FileShare.Delete | FileShare.ReadWrite)))
        {
            while (!_stopMonitoring)
            {
                Thread.Sleep(500);

                while ((line = reader.ReadLine()) != null)
                {
                    //...Do stuff with the lines
                }
            }
        }
    }
}
Paul Fleming
  • 24,238
  • 8
  • 76
  • 113
Kepar
  • 45
  • 4

3 Answers3

1

You could extract the directory name from the monitor file path. Then after your readLine loop: Get the file list in the directory, sorted by last updated date take the first item in the list compare it to the file name you are reading from and if they are different update your reader

This works on the assumption that only files in the directory will be log files and you are always wanting to be reading from the most recently updated file

IndigoDelta
  • 1,481
  • 9
  • 11
  • unfortunately this is not the case for my specific problem. Our application writes a lot of different logfiles to the same folder. – Kepar May 21 '11 at 20:55
1

There is an MSDN example showing how you can obtain a file name from a file handle (which you have access to via the Handle property of the FileStream) using Win32 APIs, but I doubt this approach will work for files on a remote network share.

You may well be out of luck in the general case.

Chris Dickson
  • 11,964
  • 1
  • 39
  • 60
  • thanks, your answer directed me to a C# implementation that works really great [stackoverflow](http://stackoverflow.com/questions/3314239/obtain-a-filename-from-a-file-handle) (at first sight) – Kepar May 21 '11 at 20:46
0

Assuming the rolled file has a different/newer create date, could you compare the create date from the file during previous monitoring read? The access and modification times probably won't be useful, but the create date might be useful.

You might try System.IO.File.GetCreationTime, although there may other affecting factors for example:

NTFS-formatted drives may cache file meta-info, such as file creation time, for a short period of time, which is known as "file tunneling." As a result, it may be necessary to explicitly set the creation time of a file if you are overwriting or replacing an existing file.

Ryan
  • 7,835
  • 2
  • 29
  • 36