FileSystemWatcher - как отследить копирование папки с файлами? - C#
Формулировка задачи:
Не понимаю как отследить копирование или перемещение папки с файлами. Отслеживание создания отдельно файлов или отдельно папки работает замечательно. А вот если в отслеживаемую директорию скопировать или переместить папку с файлами, то FileSystemWatcher сообщит только о создании папки. MSDN говорит по этому поводу:
Но Renamed и Changed происходят только если переименовывать файл в уже существующей папке в отслеживаемой директории. Если же в отслеживаемую директорию копировать или перемещать папку с файлами, то Renamed и Changed не происходят, а происходит только Created и сообщает о создании только папки без файлов в ней.
Как решить подобную проблему?
"ОС и объект FileSystemWatcher интерпретируют действие вырезания и вставки или действие перемещения как действие переименования для папки и ее содержимого. Если вы вырезаете и вставляете папку с файлами в отслеживаемую папку, объект FileSystemWatcher сообщает как о новой только о папке, но не о ее содержимом, так как оно фактически было только переименовано. Чтобы получить уведомление о том, что содержимое папок было перемещено или скопировано в отслеживаемую папку, используйте методы обработчика событий OnChanged и OnRenamed..."
Решение задачи: «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; }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д