Secure Delete .Net
We can use a Task
to get all of the directory details since Directory.GetDirectories
can be quite slow when there are lots of directories to retrieve (e.g. C:\Windows)
Collapse
var task = Task.Factory.StartNew(() => { List<string> directoryDetails = new List<string>(); foreach (string directory in Directory.GetDirectories(startPath)) { directoryDetails.Add(directory); } return directoryDetails; }); Task failed = task.ContinueWith(t => HandleTaskError(t.Exception), TaskContinuationOptions.OnlyOnFaulted); Task ok = task.ContinueWith(t => PopulateTree(t.Result, startPath, node), TaskContinuationOptions.OnlyOnRanToCompletion);
Loading the files contained within the directory is also contained in a Task
The method GetFilesFromDirectory
starts a new task that calls Directory.GetFiles
and generates an ExplorerFileInfo
instance for each found file.
For each file retrieved, it checks the cache of 'Known File Types' for a file Icon and file type description. If one isn't found, it calls the APISHGetFileInfo
to retrieve the information. It then passes a list of ExplorerFileInfo instances to LoadFilesToList
Collapse
private void LoadFilesToList(List<ExplorerFileInfo> files) { try { this.filesList.Items.Clear(); this.filesList.BeginUpdate(); ListViewItem[] viewItems = new ListViewItem[files.Count]; for (int i = 0; i < viewItems.Length; ++i) { ExplorerFileInfo file = files[i]; string[] items = new string[]{ file.Name, file.FileSize, file.FileTypeDescription, file.LastWriteTime.ToString()}; ListViewItem listItem = new ListViewItem(items, file.Extension); listItem.Name = file.FullName; listItem.SubItems[1].Tag = file.Length; viewItems[i] = listItem; } this.filesList.Items.AddRange(viewItems); } finally { this.filesList.EndUpdate(); } }
There are a couple of things to note in LoadFilesToList.
- Use of
BeginUpdate
andEndUpdate
. Really helps with performance, but I don't see enough people using them - Building up a list of items and adding to the
ListView
usingAddRange
. This is much quicker than adding to theListView
within the loop via theItems.Add
method.
Try browsing to a location that has a large number of files in (many thousand) - performance should still be acceptable.
Collapse
if (Program.AskQuestion(Resources.DeletionPrompt) == DialogResult.Yes) { // Check here to show a message before starting a thread if (!FileCleaner.CheckForDeleteProgram()) { Program.ShowError(Resources.DeletionProgramNotFound); return; } List<string> filesToDelete = new List<string>(); foreach (ListViewItem item in this.selectedFilesList.Items) { filesToDelete.Add(item.Name); } progressWindow.Begin(0, filesToDelete.Count); // Starts the deletion process on the worker thread and displays the progress // of the operation DeletionStartArguments arguments = new DeletionStartArguments(filesToDelete, UserOptions.Current.NumberOfPasses); this.deletionWorker.RunWorkerAsync(arguments); progressWindow.ShowDialog(this); }
using (Process p = new Process()) { p.StartInfo.FileName = Resources.DeletionProgram; p.StartInfo.Arguments = string.Format("-p {0} -q \"{1}\"", passes, fileName); p.StartInfo.CreateNoWindow = true; p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.Start(); string output = p.StandardOutput.ReadToEnd(); p.WaitForExit(); fileDeleted = !File.Exists(fileName); if (UserOptions.Current.LogOperations) { log.Info(output); log.Info(string.Format(Resources.FileDeletionStatus, fileName, fileDeleted.ToString())); } }