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)
{
this.Processed = 0;
this.Total = 0;
var scanPath = new DirectoryInfo(path);
if (scanPath.Exists)
{
Discover(scanPath);
Scan(scanPath);
}
}
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
}
}