Разрешить FileSystemWatcher и WriteTime / CreationTime просматривать подкаталоги? - PullRequest
0 голосов
/ 19 июня 2020

Мне было поручено создать программу, которая будет отслеживать изменения в любых файлах и подкаталогах, поэтому у меня была трещина в c# Visual Studio 2010, и я получал сбои при редактировании всего, что находится в папке. Windows 10 64-битная ОС:

Код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace IDGFileSystemWatcher
{
    class Program
    {
        public static DateTime modification = File.GetLastWriteTime(@"C:\Users\SIMPSJSH\Documents\Lets Test");
        public static DateTime creation = File.GetCreationTime(@"C:\Users\SIMPSJSH\Documents\Lets Test");
        static void Main(string[] args)
        {
            string path = @"C:\Users\SIMPSJSH\Documents\Lets Test";
            MonitorDirectory(path);

            Console.ReadKey();
        }
        private static void MonitorDirectory(string path)
        {
            //This is declaring the filewatching method, and stating to watch the path declared eariler
            FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
            fileSystemWatcher.Path = path;
            //Makes a reference to the directory. Although we already have one to the path, the array needs it in Directory info format as can't convert string format to Directory IO form.
            DirectoryInfo di = new DirectoryInfo(@"C:\Users\SIMPSJSH\Documents\Lets Test");
            // Get a reference to each file in that directory.
            FileInfo[] fiArr = di.GetFiles();
            // Display the names and sizes of the files.
            Console.WriteLine("The directory {0} contains the following files:", di.Name);
            foreach (FileInfo f in fiArr)
            {
                Console.WriteLine("The size of {0} is {1} bytes.    Created: {2}", f.Name, f.Length, creation);
            }
            //Splitting off the intial info from the change log
            Console.WriteLine("\n \n \n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n        Begin Change Log\n \n \n");
            //Watches SubDirectories
            fileSystemWatcher.IncludeSubdirectories = true;
            //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;
            //This is the actual monitoring of the files. These are the methods we call later.
            fileSystemWatcher.Created += FileSystemWatcher_Created;
            fileSystemWatcher.Changed += FileSystemWatcher_Changed;
            fileSystemWatcher.Renamed += FileSystemWatcher_Renamed;
            fileSystemWatcher.Deleted += FileSystemWatcher_Deleted;
            fileSystemWatcher.Error += new ErrorEventHandler(OnError);
            fileSystemWatcher.Renamed += new RenamedEventHandler(OnRenamed);
            //Enables the monitoring
            fileSystemWatcher.EnableRaisingEvents = true;

        }
        //These static voids each call what they should be doing (e.g monitoring if anything in the directory is renamed) and is then making a log if it is changed.
        private static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File created: {0}    at {1}\n", e.Name, modification);
        }
        private static void FileSystemWatcher_Renamed(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File renamed: {0}    at {1}", e.Name, modification);
        }
        private static void FileSystemWatcher_Deleted(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File deleted: {0}    at {1}\n", e.Name, modification);
        }
        private static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File Changed/Edited/saved: {0}", e.Name);
            var info = new FileInfo(e.FullPath);
            var theSize = info.Length;

            Console.WriteLine("The file is {0} bytes and is located at {1} \nThis file was created on {3} \nThis file was changed at {2} \n \n", theSize, info, modification, creation);
        }
        private static void OnRenamed(object source, RenamedEventArgs e)
        {
            // Specify what is done when a file is renamed.
            Console.WriteLine("(More details)File: {0} renamed to {1}    at {2}\n", e.OldFullPath, e.FullPath, modification);
        }

        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));
            }
        }
    }
}

Вверху я объявляю datetimeModification и Creation. Я считаю, что именно поэтому он вылетает, поскольку они помечены, чтобы они не могли видеть подкаталоги, тогда как их вызывают для файлов в подкаталоге. Как мне go это сделать?

Ошибка:

Unhandled Exception: System.IO.FileNotFoundException: Could not find file 'C:\Users\SIMPSJSH\Documents\Lets Test\This is for folder checking'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileInfo.get_Length()
   at IDGFileSystemWatcher.Program.FileSystemWatcher_Changed(Object sender, FileSystemEventArgs e) in c:\users\simpsjsh\documents\visual studio 2010\Projects\System monitor\System monitor\Program.cs:line 81
   at System.IO.FileSystemWatcher.OnChanged(FileSystemEventArgs e)
   at System.IO.FileSystemWatcher.NotifyFileSystemEventArgs(Int32 action, String name)
   at System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* overlappedPointer)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

1 Ответ

0 голосов
/ 19 июня 2020

Ответ пользователя @ Jimi

Может быть, потому что у вас есть var theSize = info.Length;, но измененный элемент может быть каталогом, поэтому вы получите исключение? Кстати, вы дважды подписываетесь на событие Renamed. Кроме того, событие Changed возникает несколько раз для одного и того же объекта. Кстати, вы можете установить буфер большего размера. Буфер FSW может заполниться, но вам действительно нужно заблокировать обработчик событий с помощью кода syn c и одновременно получать много уведомлений, прежде чем вы начнете терять некоторые.

...