FileSystemWatcher - как отследить копирование папки с файлами? - C#

Узнай цену своей работы

Формулировка задачи:

Не понимаю как отследить копирование или перемещение папки с файлами. Отслеживание создания отдельно файлов или отдельно папки работает замечательно. А вот если в отслеживаемую директорию скопировать или переместить папку с файлами, то FileSystemWatcher сообщит только о создании папки. MSDN говорит по этому поводу:

"ОС и объект FileSystemWatcher интерпретируют действие вырезания и вставки или действие перемещения как действие переименования для папки и ее содержимого. Если вы вырезаете и вставляете папку с файлами в отслеживаемую папку, объект FileSystemWatcher сообщает как о новой только о папке, но не о ее содержимом, так как оно фактически было только переименовано. Чтобы получить уведомление о том, что содержимое папок было перемещено или скопировано в отслеживаемую папку, используйте методы обработчика событий OnChanged и OnRenamed..."

Но Renamed и Changed происходят только если переименовывать файл в уже существующей папке в отслеживаемой директории. Если же в отслеживаемую директорию копировать или перемещать папку с файлами, то Renamed и Changed не происходят, а происходит только Created и сообщает о создании только папки без файлов в ней. Как решить подобную проблему?

Решение задачи: «FileSystemWatcher - как отследить копирование папки с файлами?»

textual
Листинг программы
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Timers;
 
namespace Test
{
    public class Service
    {
        private FileSystemWatcher watcher;
        private volatile bool enabled = true;
        private List<string> fileAndFolderList;
        private System.Timers.Timer timer;
 
        public Service()
        {
            watcher = new FileSystemWatcher( this.aesSource );
            watcher.IncludeSubdirectories = true;
            watcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName;
            watcher.Created += new FileSystemEventHandler( Watcher_Created );
 
            fileAndFolderList = new List<string>();
 
            timer = new System.Timers.Timer();
            timer.Interval = 3000;
            timer.AutoReset = false;
            timer.Elapsed += Timer_Elapsed;
        }
 
        public void OnStart()
        {
            Thread serviceThread = new Thread( new ThreadStart( this.Start ) );
            serviceThread.Name = "TestService";
            serviceThread.Start();
        }
 
        private void Start()
        {
            watcher.EnableRaisingEvents = true;
 
            while ( enabled )
            {
                Thread.Sleep( 100 );
            }
        }
 
        public void OnStop()
        {
            this.Stop();
            Thread.Sleep( 1000 );
        }
 
        private void Stop()
        {
            watcher.EnableRaisingEvents = false;
            enabled = false;
        }
 
        private void Watcher_Created( object sender, FileSystemEventArgs e )
        {
            lock ( this )
            {
                fileAndFolderList.Add( e.FullPath );
            }
 
            if ( PathIsDirectory( e.FullPath ) )
            {
                timer.Enabled = false;
                Thread.Sleep( 100 );
                timer.Enabled = true;
            }
            else
            {
                WaitForFileCopy( e.FullPath );
            }
        }
 
        private void Timer_Elapsed( Object source, ElapsedEventArgs e )
        {
            lock ( this )
            {
                foreach ( var item in fileAndFolderList )
                {
                    if ( PathIsDirectory( item ) )
                    {
                        TraverseTree( item );
                    }
                    else
                    {
                        RecordEntry( item );
                    }
                }
 
                fileAndFolderList.Clear();
            }
        }
 
        private void RecordEntry( string filePath )
        {
            try
            {
                lock ( this )
                {
                    using ( StreamWriter writer = new StreamWriter( @"D:\Delete\templog.txt", true ) )
                    {
                        writer.WriteLine( filePath );
                        writer.Flush();
                    }
                }
            }
            catch
            {
                throw new ArgumentException();
            }
        }
 
        private void TraverseTree( string pathToFolder )
        {
            //https://msdn.microsoft.com/ru-ru/library/bb513869.aspx
            // Data structure to hold names of subfolders to be
            // examined for files.
            Stack<string> dirs = new Stack<string>();
 
            if ( !System.IO.Directory.Exists( pathToFolder ) )
            {
                throw new ArgumentException();
            }
 
            dirs.Push( pathToFolder );
 
            while ( dirs.Count > 0 )
            {
                string currentDir = dirs.Pop();
                string[] subDirs;
                try
                {
                    subDirs = System.IO.Directory.GetDirectories( currentDir );
                }
                // An UnauthorizedAccessException exception will be thrown if we do not have
                // discovery permission on a folder or file. It may or may not be acceptable 
                // to ignore the exception and continue enumerating the remaining files and 
                // folders. It is also possible (but unlikely) that a DirectoryNotFound exception 
                // will be raised. This will happen if currentDir has been deleted by
                // another application or thread after our call to Directory.Exists. The 
                // choice of which exceptions to catch depends entirely on the specific task 
                // you are intending to perform and also on how much you know with certainty 
                // about the systems on which this code will run.
                catch ( UnauthorizedAccessException e )
                {
                    Console.WriteLine( e.Message );
                    continue;
                }
                catch ( System.IO.DirectoryNotFoundException e )
                {
                    Console.WriteLine( e.Message );
                    continue;
                }
 
                string[] files = null;
                try
                {
                    files = System.IO.Directory.GetFiles( currentDir );
                }
                catch ( UnauthorizedAccessException e )
                {
 
                    Console.WriteLine( e.Message );
                    continue;
                }
                catch ( System.IO.DirectoryNotFoundException e )
                {
                    Console.WriteLine( e.Message );
                    continue;
                }
                // Perform the required action on each file here.
                // Modify this block to perform your required task.
                foreach ( string file in files )
                {
                    try
                    {
                        // Perform whatever action is required in your scenario.
                        System.IO.FileInfo fi = new System.IO.FileInfo( file );
 
                        if ( !fileAndFolderList.Contains( fi.FullName ) )
                        {
                            RecordEntry( fi.FullName );
                        }
                    }
                    catch ( System.IO.FileNotFoundException e )
                    {
                        // If file was deleted by a separate application
                        //  or thread since the call to TraverseTree()
                        // then just continue.
                        Console.WriteLine( e.Message );
                        continue;
                    }
                }
 
                // Push the subdirectories onto the stack for traversal.
                // This could also be done before handing the files.
                foreach ( string str in subDirs )
                    dirs.Push( str );
            }
        }
 
        private void WaitForFileCopy( string fileName )
        {
            //https://social.msdn.microsoft.com/Forums/vstudio/en-US/5695490c-a644-48a3-be2b-cfb762cf4765/filesystemwatcher-has-to-wait-until-file-is-fully-written?forum=netfxbcl
            while ( true )
            {
                try
                {
                    lock ( this )
                    {
                        using ( StreamReader stream = new StreamReader( fileName ) )
                        {
                            timer.Enabled = true;
                            break;
                        }
                    }
                }
                catch
                {
                    timer.Enabled = false;
                    Thread.Sleep( 100 );
                }
            }
        }
 
        private bool PathIsDirectory( string path )
        {
            return ( Directory.Exists( path ) ) ? true : false;
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 3.778 из 5
Похожие ответы