private void tree_OnDeleteRequest(object sender, DeleteRequestFromTreeEventArgs e) { try { var deletePath = e.Directory; // To simplify the code here there is only the RecycleBinWithQuestion or simulate possible here // (all others will be ignored) SystemFunctions.ManuallyDeleteDirectory(deletePath, (DeleteModes)Properties.Settings.Default.delete_mode); // Remove root node this.tree.RemoveNode(deletePath); this.Data.AddLogMessage("Manually deleted: \"" + deletePath + "\" including all subdirectories"); // Disable the delete button because the user has to re-scan after he manually deleted a directory this.btnDelete.Enabled = false; } catch (System.OperationCanceledException) { // The user canceled the deletion } catch (Exception ex) { this.Data.AddLogMessage("Could not manually delete \"" + e.Directory + "\" because of the following error: " + ex.Message); MessageBox.Show(this, "The directory was not deleted, because of the following error:" + Environment.NewLine + ex.Message); } }
private void secureDelete(string path) { var emptyDirectory = new DirectoryInfo(path); if (!emptyDirectory.Exists) { throw new Exception("Could not delete the directory \"" + emptyDirectory.FullName + "\" because it does not exist anymore."); } // Cleanup folder String[] ignoreFileList = this.Data.GetIgnoreFileList(); FileInfo[] Files = emptyDirectory.GetFiles(); if (Files != null && Files.Length != 0) { // loop trough files and cancel if containsFiles == true for (int f = 0; f < Files.Length; f++) { var file = Files[f]; string delPattern = ""; bool deleteTrashFile = SystemFunctions.MatchesIgnorePattern(file, (int)file.Length, this.Data.IgnoreEmptyFiles, ignoreFileList, out delPattern); // If only one file is good, then stop. if (deleteTrashFile) { try { SystemFunctions.SecureDeleteFile(file, this.Data.DeleteMode); this.Data.AddLogMessage(String.Format("-> Successfully deleted file \"{0}\" because it matched the ignore pattern \"{1}\"", file.FullName, delPattern)); } catch (Exception ex) { this.Data.AddLogMessage(String.Format("Failed to delete file \"{0}\" - Error message: \"{1}\"", file.FullName, ex.Message)); var msg = "Could not delete this empty (trash) file:" + Environment.NewLine + file.FullName + Environment.NewLine + Environment.NewLine + "Error message: " + ex.Message; if (ex is REDPermissionDeniedException) { throw new REDPermissionDeniedException(msg, ex); } else { throw new Exception(msg, ex); } } } } } // End cleanup // This function will ensure that the directory is really empty before it gets deleted SystemFunctions.SecureDeleteDirectory(emptyDirectory.FullName, this.Data.DeleteMode); }
void Default_SettingChanging(object sender, System.Configuration.SettingChangingEventArgs e) { if (e.SettingName == "keep_system_folders" && !(bool)e.NewValue) { if (MessageBox.Show(this, SystemFunctions.ConvertLineBreaks(RED2.Properties.Resources.warning_really_delete), RED2.Properties.Resources.warning, MessageBoxButtons.OKCancel, MessageBoxIcon.Asterisk) == DialogResult.Cancel) { e.Cancel = true; } } }
private void btnExplorerRemove_Click(object sender, EventArgs e) { SystemFunctions.AddOrRemoveRegKey(false); this.btnExplorerRemove.Enabled = false; this.btnExplorerIntegrate.Enabled = true; }
private void btnShowConfig_Click(object sender, EventArgs e) { SystemFunctions.OpenDirectoryWithExplorer(Application.StartupPath); }
/// <summary> /// Let the user select a folder /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnChooseFolder_Click(object sender, EventArgs e) { Properties.Settings.Default.last_used_directory = SystemFunctions.ChooseDirectoryDialog(Properties.Settings.Default.last_used_directory); }
private void init() { this.tree = new TreeManager(this.tvFolders); this.tree.OnProtectionStatusChanged += new EventHandler <ProtectionStatusChangedEventArgs>(tree_OnProtectionStatusChanged); this.tree.OnDeleteRequest += new EventHandler <DeleteRequestFromTreeEventArgs>(tree_OnDeleteRequest); this.lbAppTitle.Text += string.Format("{0}", Assembly.GetExecutingAssembly().GetName().Version.ToString()); #region Bind config settings to controls // Read folder from the config file this.tbFolder.DataBindings.Add("Text", Properties.Settings.Default, "last_used_directory"); this.cbIgnoreHiddenFolders.DataBindings.Add("Checked", Properties.Settings.Default, "dont_scan_hidden_folders"); this.cbIgnore0kbFiles.DataBindings.Add("Checked", Properties.Settings.Default, "ignore_0kb_files"); this.cbKeepSystemFolders.DataBindings.Add("Checked", Properties.Settings.Default, "keep_system_folders"); this.cbClipboardDetection.DataBindings.Add("Checked", Properties.Settings.Default, "clipboard_detection"); this.cbHideScanErrors.DataBindings.Add("Checked", Properties.Settings.Default, "hide_scan_errors"); this.tbIgnoreFiles.DataBindings.Add("Text", Properties.Settings.Default, "ignore_files"); this.tbIgnoreFolders.DataBindings.Add("Text", Properties.Settings.Default, "ignore_directories"); this.nuMaxDepth.DataBindings.Add("Value", Properties.Settings.Default, "max_depth"); this.nuInfiniteLoopDetectionCount.DataBindings.Add("Value", Properties.Settings.Default, "infinite_loop_detection_count"); this.nuPause.DataBindings.Add("Value", Properties.Settings.Default, "pause_between"); this.cbIgnoreErrors.DataBindings.Add("Checked", Properties.Settings.Default, "ignore_deletion_errors"); // Special field this.lblRedStats.Text = String.Format(RED2.Properties.Resources.red_deleted, Properties.Settings.Default.delete_stats); // Delete mode foreach (var d in DeleteModeItem.GetList()) { this.cbDeleteMode.Items.Add(new DeleteModeItem(d)); } this.cbDeleteMode.DataBindings.Add("SelectedIndex", Properties.Settings.Default, "delete_mode"); #region Check if the user started RED as admin var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { var isIntegrated = SystemFunctions.IsRegKeyIntegratedIntoWindowsExplorer(); this.btnExplorerIntegrate.Enabled = !isIntegrated; this.btnExplorerRemove.Enabled = isIntegrated; this.Text += " (Admin mode)"; } else { this.lblReqAdmin.ForeColor = Color.Red; this.btnExplorerIntegrate.Enabled = false; this.btnExplorerRemove.Enabled = false; } #endregion var credits = Path.Combine(Application.StartupPath, "credits.txt"); if (File.Exists(credits)) { this.tbCredits.AppendText(File.ReadAllText(credits)); } else { this.tbCredits.AppendText("Error: Could not find the credits text file:" + Environment.NewLine + credits); } this.nuFolderAge.DataBindings.Add("Value", Properties.Settings.Default, "min_folder_age_hours"); #endregion this.lbStatus.Text = ""; this.cmStrip.Enabled = false; this.pbProgressStatus.Maximum = 100; this.pbProgressStatus.Minimum = 0; this.pbProgressStatus.Step = 5; this.btnShowLog.Enabled = false; drawDirectoryIcons(); #region Read and apply command line arguments string[] args = Environment.GetCommandLineArgs(); if (args.Length > 1) { args[0] = ""; var path = String.Join("", args).Replace("\"", "").Trim(); // add ending backslash if (!path.EndsWith("\\")) { path += "\\"; } Properties.Settings.Default.last_used_directory = path; } #endregion }
private void openFolderToolStripMenuItem_Click(object sender, EventArgs e) { SystemFunctions.OpenDirectoryWithExplorer(this.tree.GetSelectedFolderPath()); }
/// <summary> /// User clicks twice on a folder /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void tvFolders_DoubleClick(object sender, EventArgs e) { SystemFunctions.OpenDirectoryWithExplorer(this.tree.GetSelectedFolderPath()); }
private DirectorySearchStatusTypes checkIfDirectoryEmpty(DirectoryInfo startDir, int depth) { if (this.PossibleEndlessLoop > this.Data.InfiniteLoopDetectionCount) { this.ReportProgress(0, new FoundEmptyDirInfoEventArgs(startDir.FullName, DirectorySearchStatusTypes.Error, "Aborted - possible infinite-loop detected")); return(DirectorySearchStatusTypes.Error); } try { // Thread.Sleep(500); -> ? if (this.Data.MaxDepth != -1 && depth > this.Data.MaxDepth) { return(DirectorySearchStatusTypes.NotEmpty); } // Cancel process if the user hits stop if (CancellationPending) { return(DirectorySearchStatusTypes.NotEmpty); } this.folderCount++; // update status progress bar after 100 steps: if (this.folderCount % 100 == 0) { this.ReportProgress(folderCount, "Checking directory: " + startDir.Name); } bool containsFiles = false; // Get file list FileInfo[] fileList = null; // some directories could trigger a exception: try { fileList = startDir.GetFiles(); } catch { fileList = null; } if (fileList == null) { // CF = true = folder does not get deleted: containsFiles = true; // secure way this.Data.AddLogMessage("Failed to access files in \"" + startDir.FullName + "\""); this.ReportProgress(0, new FoundEmptyDirInfoEventArgs(startDir.FullName, DirectorySearchStatusTypes.Error, "Failed to access files")); } else if (fileList.Length == 0) { containsFiles = false; } else { string delPattern = ""; // loop trough files and cancel if containsFiles == true for (int f = 0; (f < fileList.Length && !containsFiles); f++) { FileInfo file = null; int filesize = 0; try { file = fileList[f]; filesize = (int)file.Length; } catch { // keep folder if there is a strange file that // triggers a exception: containsFiles = true; break; } // If only one file is good, then stop. if (!SystemFunctions.MatchesIgnorePattern(file, filesize, this.Data.IgnoreEmptyFiles, this.ignoreFileList, out delPattern)) { containsFiles = true; } } } // If the folder does not contain any files -> get subfolders: DirectoryInfo[] subFolderList = null; try { subFolderList = startDir.GetDirectories(); } catch { // If we can not read the folder -> don't delete it: this.Data.AddLogMessage("Failed to access subdirectories in \"" + startDir.FullName + "\""); this.ReportProgress(0, new FoundEmptyDirInfoEventArgs(startDir.FullName, DirectorySearchStatusTypes.Error, "Failed to access subdirectories")); return(DirectorySearchStatusTypes.Error); } // The folder is empty, break here: if (!containsFiles && subFolderList.Length == 0) { return(DirectorySearchStatusTypes.Empty); } bool allSubDirectoriesEmpty = true; foreach (var curDir in subFolderList) { var attribs = curDir.Attributes; // Hidden folder? bool ignoreSubDirectory = (this.Data.IgnoreHiddenFolders && ((attribs & FileAttributes.Hidden) == FileAttributes.Hidden)); ignoreSubDirectory = (ignoreSubDirectory || (this.Data.KeepSystemFolders && ((attribs & FileAttributes.System) == FileAttributes.System))); if (!ignoreSubDirectory && checkIfDirectoryIsOnIgnoreList(curDir)) { this.Data.AddLogMessage("Aborted scan of \"" + curDir.FullName + "\" because it is on the ignore list."); this.ReportProgress(0, new FoundEmptyDirInfoEventArgs(curDir.FullName, DirectorySearchStatusTypes.Ignore)); ignoreSubDirectory = true; } if (!ignoreSubDirectory && (attribs & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) { this.Data.AddLogMessage("Aborted scan of \"" + curDir.FullName + "\" because it is a symbolic link"); this.ReportProgress(0, new FoundEmptyDirInfoEventArgs(curDir.FullName, DirectorySearchStatusTypes.Error, "Aborted because dir is a symbolic link")); ignoreSubDirectory = true; } // TODO: Implement more checks //else if ((attribs & FileAttributes.Device) == FileAttributes.Device) msg = "Device - Aborted - found"; //else if ((attribs & FileAttributes.Encrypted) == FileAttributes.Encrypted) msg = "Encrypted - found"; // The file will not be indexed by the operating system's content indexing service. // else if ((attribs & FileAttributes.NotContentIndexed) == FileAttributes.NotContentIndexed) msg = "NotContentIndexed - Device found"; //else if ((attribs & FileAttributes.Offline) == FileAttributes.Offline) msg = "Offline - found"; //else if ((attribs & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) msg = "ReadOnly - found"; //else if ((attribs & FileAttributes.Temporary) == FileAttributes.Temporary) msg = "Temporary - found"; // Scan sub folder: var subFolderStatus = DirectorySearchStatusTypes.NotEmpty; if (!ignoreSubDirectory) { // JRS ADDED check for AGE of folder if (curDir.CreationTime.AddHours(this.Data.MinFolderAgeHours) < DateTime.Now) { subFolderStatus = this.checkIfDirectoryEmpty(curDir, depth + 1); } else { this.Data.AddLogMessage(String.Format(RED2.Properties.Resources.young_folder_skipped, curDir.FullName, this.Data.MinFolderAgeHours.ToString(), curDir.CreationTime.ToString())); } // Report status to the GUI if (subFolderStatus == DirectorySearchStatusTypes.Empty) { this.ReportProgress(0, new FoundEmptyDirInfoEventArgs(curDir.FullName, subFolderStatus)); } } // this folder is not empty: if (subFolderStatus != DirectorySearchStatusTypes.Empty || ignoreSubDirectory) { allSubDirectoriesEmpty = false; } } // All subdirectories are empty return((allSubDirectoriesEmpty && !containsFiles) ? DirectorySearchStatusTypes.Empty : DirectorySearchStatusTypes.NotEmpty); } catch (Exception ex) { // Error handling if (ex is System.IO.PathTooLongException) { this.PossibleEndlessLoop++; } this.Data.AddLogMessage("An unknown error occurred while trying to scan this directory: \"" + startDir.FullName + "\" - Error message: " + ex.Message); this.ReportProgress(0, new FoundEmptyDirInfoEventArgs(startDir.FullName, DirectorySearchStatusTypes.Error, ex.Message)); return(DirectorySearchStatusTypes.Error); } }