using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace mdfinder { /// Scans directories, logging files and their attributes. public class Scanner : PropertyChangedAlerter { #region Members /// Event queue for all listeners interested in FilesFound events. public event EventHandler FilesFound; /// Event queue for all listeners interested in DirectoryFound events. public event EventHandler DirectoryFound; /// Event queue for all listeners interested in ReportProgress events. public event EventHandler ReportProgress; private uint processed; private uint total; private bool isScanning; #endregion #region Properties public uint Processed { get { return this.processed; } private set { this.processed = value; OnPropertyChanged(); } } public uint Total { get { return this.total; } private set { this.total = value; OnPropertyChanged(); } } public bool IsScanning { get { return this.isScanning; } private set { this.isScanning = value; OnPropertyChanged(); } } #endregion #region Methods public void Scan(string path) { if(string.IsNullOrWhiteSpace(path)) { this.IsScanning = false; return; } this.Processed = 0; this.Total = 0; this.IsScanning = true; var scanPath = new DirectoryInfo(path); if (scanPath.Exists) { Discover(scanPath); Scan(scanPath); } this.IsScanning = false; } private void Discover(DirectoryInfo directory) { try { this.Total += (uint)directory.EnumerateFiles().Count(); foreach (var subdirectory in directory.GetDirectories()) { OnDirectoryFound(subdirectory); Discover(subdirectory); } } catch (UnauthorizedAccessException unauthorizedAccessException) { //Ignore and just continue. } catch (DirectoryNotFoundException directoryNotFoundException) { //Ignore and continue. } } private void Scan(DirectoryInfo directory) { try { var fileBatches = directory.EnumerateFiles().Bin(Properties.Settings.Default.FilesFoundAlert); var subdirectories = directory.GetDirectories(); foreach (var subdirectory in subdirectories) { Scan(subdirectory); } foreach (var batch in fileBatches) { OnFilesFound(batch); this.Processed += (uint)batch.Count(); OnReportProgress(this.Processed, this.Total); } } catch (UnauthorizedAccessException unauthorizedAccessException) { //Ignore and just continue. } } /// Executes the files found action. /// The files. private void OnFilesFound(IEnumerable files) { this.FilesFound?.Invoke(this, new FilesFoundEventArgs(files)); } /// Executes the directory found action. /// Pathname of the directory. private void OnDirectoryFound(DirectoryInfo directory) { this.DirectoryFound?.Invoke(this, new DirectoryFoundEventArgs(directory)); } /// Executes the report progress action. /// The processed. /// Number of. private void OnReportProgress(uint processed, uint total) { this.ReportProgress?.Invoke(this, new ProgressReportEventArgs(processed, total)); } #endregion #region Subclasses /// Event arguments describing the state of the when it has found files. public class FilesFoundEventArgs : EventArgs { #region Properties /// Gets or sets the files. /// The files. public IEnumerable Files { get; private set; } #endregion #region Constructors /// Constructor. /// The files. public FilesFoundEventArgs(IEnumerable files) { this.Files = files; } #endregion } /// Event arguments describing the state of the when it has found a directory. public class DirectoryFoundEventArgs : EventArgs { #region Properties /// Gets or sets the pathname of the directory. /// The pathname of the directory. public DirectoryInfo Directory { get; private set; } #endregion #region Constructors /// Constructor. /// The pathname of the directory. public DirectoryFoundEventArgs(DirectoryInfo directory) { this.Directory = directory; } #endregion } public class ProgressReportEventArgs : EventArgs { #region Properties /// Gets or sets the progress as a percentage. /// The percentage. public double Percentage { get { return ((double)this.Processed / (double)this.Total); } } /// Gets or sets the number of processed items. /// The processed. public uint Processed { get; private set; } /// Gets or sets the number of items discovered to process. /// The total. public uint Total { get; private set; } #endregion #region Constructors /// Constructor. /// The processed item count. /// The total discovereditem count. public ProgressReportEventArgs(uint processed, uint total) { this.Processed = processed; this.Total = total; } #endregion } #endregion } }