FileSystemWatcher 监控 2 个目录。更改日志每次更改增加 1,所以当控制台中的一个文件更改时它会弹出多次?

FileSystemWatcher monitoring 2 directories. Change log increased by 1 per change, so when one file changes in console it pops up many times?

所以我有一个包含不同文件夹的大目录,我一次只需要监视一个,需要监视的那个是由我从单独的一个完全独立的文件中获得的某些信息确定的目录。可以使用不同的信息更新此文件,这意味着我监视更改的目录将更改。我已经完成了所有这些工作,但是它引入了一个奇怪的错误。让我们调用始终监视作业编号的单个文件 - 当前作业: 因此,当我在最初加载的目录(许多工作文件夹之一)中看到文件更改时,它会弹出一次,说它在我的控制台中发生了更改,完美!但是当当前作业文件被更改并保存时,它在控制台中说它已经存在了,太棒了!但是,在所有作业的作业文件夹中,我现在正在监视一个不同的文件夹(由当前作业中的信息确定),并且此文件夹中的任何更改都会在控制台中弹出 2 次。那么如果当前的job document改变了,这个issue是3,然后是4,然后是5,线性递增。 任何人 运行 进入类似或可以找出我搞砸了什么?甚至指导我停止欺骗?

这是代码:(不是程序员,它可能看起来很乱 - 非常新,任务是为了工作这样做):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Timers;


namespace EKMasterMonitoring
{
    class Program
    {
        //These values are being accessed at multiple methods in the program so simpler to declare them in the class allowing everything to easily call them
        public static DateTime modification = File.GetLastWriteTime(@"C:\Users\SIMPSJSH\Documents\Master\Zeichnungsdaten");
        public static DateTime creation = File.GetCreationTime(@"C:\Users\SIMPSJSH\Documents\Master\Zeichnungsdaten");
        public static string Spacer = "\r\n----------------------------------------------------\r\n";

        public static string path = "";
        public static string AreaOfMonitor = "";
        //This is for monitoring in  method "Monitor Directory" I've declared it in class as it has to be disabled by another method seperate to "Monitor Directory"
        public static FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();


        public static string ProgramChange = @"C:\Users\SIMPSJSH\Documents\Master\Daten";

        static void Main(string[] args)
        {
            //Runs method to grab current job as well as monitor it incase it changes
            ProgramSwapMonitor(ProgramChange);
            GetCurrentJob();

            // shouldn't need no more string path = "";
            path = AreaOfMonitor;
            MonitorDirectory(path);
            

            //Bool for the Loop just ensuring hitting the keyboard or anything daft wont close the program
            bool Running = true;
            Console.WriteLine("Type 'quit' to exit program");
            //This was mildly lazy but also I had a weird issue that naming it path solved, Don't really understand but it worked... ANYWAY - This is just storing the path to be used for monitoring
            

            while (Running)
            {
                
                string exit = Console.ReadLine();

                if (exit.ToUpper() == "quit".ToUpper())
                {
                    Running = false;
                }

            }
        }
        private static void GetCurrentJob()
        {
            //This gets the file
            string CurrentJobPath = @"C:\Users\SIMPSJSH\Documents\Master\Daten\dnocontainer.cfg";

            //This makes it so it only reads the 5th line of the notepad and ignore everything else
            string line = File.ReadLines(CurrentJobPath).Skip(4).Take(1).First();
            //This is getting rid of all parts of the line I don't care about
            line = line.Replace(" ", "").Replace("(STRING)Dno=", "").Replace("\"", "").Replace(";", "");

            //This isn't necessary but I like it okay
            string JobName = line;
            //Testing To prove its behaving
            Console.WriteLine(JobName);
            //This is making a path to the exact folder for the job currently running
            AreaOfMonitor = @"C:\Users\SIMPSJSH\Documents\Master\Zeichnungsdaten\" + JobName;
            Console.WriteLine(AreaOfMonitor);
            
    

        }
        private static void ProgramSwapMonitor(string ProgramChange)
        {
            // Create a new FileSystemWatcher and set its properties.
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = ProgramChange;

            /* Watch for changes in LastAccess and LastWrite times, and 
               the renaming of files or directories. */

            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
               | NotifyFilters.FileName | NotifyFilters.DirectoryName;

            // Only watch text This File
            watcher.Filter = "dnocontainer.cfg";

            // Add event handlers.
            watcher.Changed += new FileSystemEventHandler(OnChanged);
            watcher.Created += new FileSystemEventHandler(OnChanged);
            watcher.Deleted += new FileSystemEventHandler(OnChanged);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);

            // Begin watching.
            watcher.EnableRaisingEvents = true;
        }
        // Define the event handlers.
        private static void OnChanged(object source, FileSystemEventArgs e)
        {
            // Specify what is done when a file is changed, created, or deleted.
            Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
            Console.WriteLine(Spacer);
            
            //This disables the directory monitor, then changes the active job in its memory, then restarts the directory monitor so it can now monitor the new location.
            fileSystemWatcher.EnableRaisingEvents= false;
            GetCurrentJob();
           
            MonitorDirectory(path);


        }

        private static void OnRenamed(object source, RenamedEventArgs e)
        {
            // Specify what is done when a file is renamed.
            Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
            GetCurrentJob();
        }
        
        //AS MONITORING 2 SEPERATE DIRECTORIES WE NEED 2 SEPERATE INSTANCES OF FILE SYSTEM WATCHER
        //Break
        //Break
        //Break
        //Break

        public static void MonitorDirectory(string path)
        {
                fileSystemWatcher.EnableRaisingEvents = false;                           
                path = AreaOfMonitor;

                fileSystemWatcher.Path = path;


                //Allows monitoring of subdirectories. - Not needed as shouldn't be any:
                //FileSystemWatcher.IncludeSubdirectories = true;

                //Splitting off the intial info from the change log
                Console.WriteLine("\r\n \r\n \r\n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \r\n        Begin Change Log\r\n \r\n \r\n");

                //Declaring the filters, I don't really know why its needed for the monitoring of changes, creation, deletion ECT but it is.
                fileSystemWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                

                //Calling the SystemWatcherFunctions
                fileSystemWatcher.Changed += FileSystemWatcher_Changed;
                fileSystemWatcher.Error += new ErrorEventHandler(OnError);

                Console.WriteLine("This is monitoring {0}", path);
                //enables the monitoring
                fileSystemWatcher.EnableRaisingEvents = true;
             
        }
        private static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            //This is for the sizes and file info. We are grabbing the resutls but also creating a converted version so I can't display in MB for large file with accuracy
            var info = new FileInfo(e.FullPath);
            var size = Convert.ToInt64(0);

            //declaring to be used, double allows decimals. 64bitInt does not.
            double MBSIZE = 0;
            //This is to avoid potential error. Ensures the info we are grabbing is in the direct directory and no sub ones.
            if ((info.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
            {
                size = info.Length;
            }
            //This is for making it into megabytes for unnecessary user friendliness
            if (size > 1000000)
            {
                MBSIZE = Convert.ToDouble(size);
                MBSIZE = MBSIZE / 1000000;

                Console.WriteLine("File Changed/Edited/saved: {0}\r\nwas modified on {1}\r\nit is {2} Megabytes in size\r\nIs was originally created on {3} {4} ", e.Name, modification, MBSIZE, creation, Spacer);
            }
            else
            {
                Console.WriteLine("File Changed/Edited/saved: {0}\r\nwas modified on {1}\r\nit is {2} bytes in size\r\nIs was originally created on {3}{4} ", e.Name, modification, size, creation, Spacer);
            }



                              
        }
        private static void OnError(object source, ErrorEventArgs e)
        {
            //  Show that an error has been detected.
            Console.WriteLine("The FileSystemWatcher has detected an error at {0}", modification);
            //  Give more information if the error is due to an internal buffer overflow.
            if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
            {
                //  This can happen if Windows is reporting many file system events quickly
                //  and internal buffer of the  FileSystemWatcher is not large enough to handle this
                //  rate of events. The InternalBufferOverflowException error informs the application
                //  that some of the file system events are being lost.
                Console.WriteLine(("The file system watcher experienced an internal buffer overflow: " + e.GetException().Message));
            }
        }
    }
}

所以解决方案:

private static void OnChanged(object source, FileSystemEventArgs e)
        {
            // Specify what is done when a file is changed, created, or deleted.
            Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
            Console.WriteLine(Spacer);

            //This disables the directory monitor, then changes the active job in its memory, then restarts the directory monitor so it can now monitor the new location.
            fileSystemWatcher.EnableRaisingEvents = false;
            GetCurrentJob();
            MonitorDirectory(path);
            fileSystemWatcher.Changed -= FileSystemWatcher_Changed;


        }

为了让 Monitor 目录更新到给定的新位置,我不得不再次重新初始化它(运行 它)。这就是我认为的问题,因为添加一行使这个问题开始,所以我的那种不是很好但实用的解决方案是每次你更改 Currentjob.txt 文件时你正在制作这个方法 运行,增加一个监控目录。所以我所做的就是添加 -=FSW_Changed 行,以便添加并立即删除。离开更新后的位置,只有 1 个结果

在 MonitorDirectory 方法中,您只是向 fileSystemWatcher.Changed 上的 FileSystemWatcher_Changed-method 添加了更多委托:

fileSystemWatcher.Changed += FileSystemWatcher_Changed;

这就是每次更改当前工作文档时您都会收到线性增加的通知的原因。