简体   繁体   中英

FileSystemWatcher raised only after first change

I am using FileSystemWatcher .

All is working fine. When I save my file, the Changed event is raised properly. But if I save file a second time, the Changed event isn't raised anymore.

Do I need to put additional code, so it would raise everytime I save a file?

Here is a part of my code, if this would be of any help:

I made a class MachineWatcher , because in my project, I need to create a list of different watcher types (but I don't think it changes anything to the question):

public class MachineWatcher
{
    private Machine machine { get; set; }
    public Machine Machine { get { return this.machine; } set { this.machine = value; } }
    private string typeWatcher { get; set; } = "";
    public string TypeWatcher { get { return this.typeWatcher; } set { this.typeWatcher = value; } }
    FileSystemWatcher watcher { get; set; }
    public FileSystemWatcher Watcher { get { return this.watcher; } set { this.watcher = value; } }
    public MachineWatcher()
    {

    }
    public MachineWatcher(string type,string directoryStock,string fileFilter)
    {
        this.typeWatcher = type;
        this.watcher = new FileSystemWatcher();
        this.watcher.Path = Path.GetDirectoryName(directoryStock);
        this.watcher.Filter = fileFilter;
        this.watcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
        this.watcher.Changed += new FileSystemEventHandler(OnFeedBackNesterCreated);
        this.watcher.Created += new FileSystemEventHandler(OnFeedBackNesterCreated);
        
        this.watcher.EnableRaisingEvents = true;
    }
    private void OnFeedBackNesterCreated(object source, FileSystemEventArgs e)
    {
        string filePath = e.FullPath;
        LaunchingOrder newLo = this.readXmlFile(filePath);
        if(newLo!=null)
        {
            newLo.Fichier = filePath;
            newLo.AddOrUpdate();
        }
    }
        
}

Reading your comments carefully, it sounds as though Excel specifically is what makes the problem show up. If that's the case, I have a theory-with-evidence that the reason you're having a problem is that an Excel Save is is not a Change .

Honestly, I would have had no idea except that I made a mock MachineWatcher and hooked up all the events including Renamed . I ran a test, first using text file and then by saving an Excel file from Excel using the regular menu save. What I discovered is that saving my existing Excel file caused the following to happen:

  1. Created event for temporary file arbitrarily named 0FE68B30 (presumably containing the changes)
  2. Renamed event for arbitrarily named file 6E0D6A48.tmp (presumably from 0FE68B30 )
  3. Renamed event for the real target, a file named ExcelTestFile.xlxs (presumably a copy operation from 6E0D6A48.tmp )
  4. Delete event for 6E0D6A48.tmp

But no Change events for the target Excel file. This was a shocker to me, but see if you can repro

Based on this experiment, my theory is that you need to add this.watcher.Renamed to the list of events to handle. You will also have to take care not to filter it out when you apply the this.watcher.NotifyFilter expression. My test methodology is shown below, but here is the result on the Excel Save operation:

测试日志


Mock a minimal MachineWatcher

public class MachineWatcher
{
    public MachineWatcher(string type, string directoryStock, string fileFilter)
    {
        watcher = new FileSystemWatcher(directoryStock, fileFilter);
        watcher.Created += onModified;
        watcher.Changed += onModified;
        watcher.Renamed += onModified;
        watcher.Deleted += onModified; 
        // watcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
        watcher.EnableRaisingEvents = true;
    }
    FileSystemWatcher watcher { get; }

    private void onModified(object sender, FileSystemEventArgs e)
    {
        switch (e.ChangeType)
        {
            case WatcherChangeTypes.Created:
                OnFeedBackNesterCreated(sender, e);
                break;
            case WatcherChangeTypes.Deleted:
                Console.WriteLine($"Deleted: {e.Name}");
                break;
            case WatcherChangeTypes.Changed:
                var ext = Path.GetExtension(e.FullPath);
                switch (ext)
                {
                    case ".xlsx":
                        Console.WriteLine($"Changed: {e.Name}");
                        break;
                    case ".txt":
                        Console.WriteLine($"Changed: {e.Name} {File.ReadAllLines(e.FullPath).Last()}");
                        break;
                    case "":
                        break;
                    default:
                        Console.WriteLine($"The '{ext}' extension is not supported");
                        break;
                }
                break;
            case WatcherChangeTypes.Renamed:
                Console.WriteLine($"Renamed: {e.Name}");
                break;
            default:
                break;
        }
    }

    private void OnFeedBackNesterCreated(object source, FileSystemEventArgs e)
    {
        Console.WriteLine($"Created: {e.Name}");
    }
}

Exercise the MachineWatcher using Console

static void Main(string[] args)
{
    const int SPACING = 500;
    string appData = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
        "custom_file_system_watcher");

    // Ensure that the root directory exists
    Directory.CreateDirectory(appData);

    // Make an instance of MachineWatcher
    var mw = new MachineWatcher(
        null, // In minimal reproducible sample this is unused
        appData, 
        "*.*");

    // Force Delete (if exists)
    var testFile = Path.Combine(appData, "testFile.txt");
    File.Delete(testFile);
    Thread.Sleep(SPACING);

    // Force Create + Change
    File.WriteAllText(
            testFile, 
            $"{DateTime.Now}{Environment.NewLine}");
    Thread.Sleep(SPACING);

    // Force N Changes
    var N = 5;
    for (int i = 1; i <= N; i++)
    {
        // Using Append because File.WriteAllText is two events not one.
        File.AppendAllText(testFile, $"Change #{i}{Environment.NewLine}");
        Thread.Sleep(SPACING);
    }

    // Force Rename
    var testFileRenamed = Path.Combine(appData, "testFile.Renamed.txt");
    File.Move(testFile, testFileRenamed, overwrite: true);

    // Prove that if the Excel file LastWriteTime changes, we'll see it
    var excelFile = Path.Combine(appData, "ExcelTestFile.xlsx");
    var fileInfo = new FileInfo(excelFile);
    if(fileInfo.Exists)
    {
        Console.WriteLine();
        Console.WriteLine("Proves that if the Excel file LastWriteTime changes, we'll see it:");
        fileInfo.LastWriteTime = DateTime.Now;
    }
    Thread.Sleep(SPACING);

    Console.WriteLine();
    Console.WriteLine("Waiting for Excel file changes...");
    Console.ReadKey();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM