Search code examples
c#filesystemwatcher

FileSystemWatcher: Ignore first change to the file


I am using FileSystemWatcher class in C# to track the changes on a file whenever the user saves the file after modifying it.

FileSystemWatcher watcher = new FileSystemWatcher()
{
    Path = DIR_NAME,
    NotifyFilter = NotifyFilters.LastWrite | 
                   NotifyFilters.CreationTime | 
                   NotifyFilters.LastAccess,
    Filter = "*.pdf",
    IncludeSubdirectories = true,
    EnableRaisingEvents = true
};

watcher.Changed += OnChanged;

However, the file that I want to track is getting created programmatically, as follows:

FileStream stream = FileUtil.CreateNewFile(filePath); // Creates a file
file.WriteFileToStream(stream); // Writes into the file

Ideally, my code is supposed to run as follows:

  1. The program will create a file and write some content into it.
  2. User opens the file, modifies it and saves.
  3. At this point, it should trigger OnChanged, i.e. I want my OnChanged handler code to execute only when a real user modifies it and saves it.

However, it's getting triggered whenever the file is getting written into programmatically, i.e. on the following line:

file.WriteFileToStream(stream);

Which is, technically, correct behavior, as it's tracking the change in the file. However, my business case doesn't allow the OnChanged handler code to be executed when the file is initially created and written into.

My question is, is there a workaround to skip the OnChanged call when the file is created and written into first time programmatically?

Note:

  1. The application architecture requires that the FileSystemWatcher is initialized when my application starts. So I cannot register it after the file is created.
  2. This is a multi-user application, where multiple users will be writing into the files simultaneously, so I cannot disable the watcher before creating the file and enable it after its created:

watcher.EnableRaisingEvents = false; 
CreateFile();
watcher.EnableRaisingEvents = true;

Solution

  • Approach One:

    1. Create and save the file in a directory that is not being watched.
    2. Move the file into the directory being watched.

    Approach Two:

    When a file is created, use OnCreated() event handler to add the file name to a filesToIgnore list.

    In the OnChanged event handler, check if the filesToIgnore list contains the file name. If it does, remove it from the list (to process it next time) and return from the handler.

    private List<string> filesToIgnore = new List<string>();
    
    private void OnCreated(object source, FileSystemEventArgs file)
    {
       filesToIgnore.Add(file.Name);
    }
    
    private void OnChanged(object source, FileSystemEventArgs file)
    {
        if(filesToIgnore.Contains(file.Name))
        {
             filesToIgnore.Remove(file.Name);
             return; 
        }
    
        // Code to execute when user saves the file
    }
    

    This approach assumes that OnCreated() will be always triggered before OnChanged().