diff --git a/SDeleteGUI/Core/ListBoxEx.cs b/SDeleteGUI/Core/ListBoxEx.cs index ca3dded..98c8985 100644 --- a/SDeleteGUI/Core/ListBoxEx.cs +++ b/SDeleteGUI/Core/ListBoxEx.cs @@ -25,6 +25,19 @@ public ListBoxEx() : base() this.SetStyle(ControlStyles.EnableNotifyMessage, true); } + + protected override CreateParams CreateParams + { + get + { + const int WS_EX_COMPOSITED = 0x02000000; + CreateParams cp = base.CreateParams; + //cp.ExStyle |= WS_EX_COMPOSITED; + return cp; + } + } + + protected override void OnNotifyMessage(Message m) { //Filter out the WM_ERASEBKGND message @@ -39,5 +52,40 @@ protected override void OnPaintBackground(PaintEventArgs pevent) } + + private void LockWindow(Control ctl) + { + // DIALOG SEND ghDlg, %WM_SETREDRAW,%FALSE,0 'do not allow messages + uom.WinAPI.Windows.SendMessage(ctl.Handle, uom.WinAPI.Windows.WindowMessages.WM_SETREDRAW, (int)0, 0); + ClearBuffers(); + } + + private void UnlockWindow(Control ctl) + { + ClearBuffers();//do not use DIALOG ENABLE or DIALOG DISABLE + uom.WinAPI.Windows.SendMessage(ctl.Handle, uom.WinAPI.Windows.WindowMessages.WM_SETREDRAW, (int)-1, 0); + /* + DIALOG SEND ghDlg, % WM_SETREDRAW,% TRUE,0 'allow messages + DIALOG REDRAW ghDlg 'required for scrollbars to refresh + */ + + //RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN) для перерисовки списка. + } + + private void ClearBuffers() + { + //http://stackoverflow.com/questions/2400332/how-to-clear-mouse-click-buffer + + + //call just before exit sub/function to prevent re-entry by stray input + /* + LOCAL SystemMsg AS TagMsg + + WHILE PeekMessage(SystemMsg,% NULL,% WM_KEYFIRST,% WM_KEYLAST, % PM_REMOVE OR % PM_NOYIELD):WEND + WHILE PeekMessage(SystemMsg,% NULL,% WM_MOUSEFIRST,% WM_MOUSELAST, % PM_REMOVE OR % PM_NOYIELD) :WEND + */ + } + + } } \ No newline at end of file diff --git a/SDeleteGUI/Core/SDelete/DataReceivedEventArgsEx.cs b/SDeleteGUI/Core/SDelete/DataReceivedEventArgsEx.cs new file mode 100644 index 0000000..9c77fc0 --- /dev/null +++ b/SDeleteGUI/Core/SDelete/DataReceivedEventArgsEx.cs @@ -0,0 +1,107 @@ +#nullable enable + + +namespace SDeleteGUI.Core.SDelete +{ + + internal class DataReceivedEventArgsEx : System.EventArgs + { + + #region OutputLocalization + + + private const string C_METHOD_TryParse = "TryParse"; + //Get all classes from 'SDeleteGUI.Core.SDelete.OutputLocalization' namespace which have static|public TryParse() method + private static Lazy _localizedOutputParsers = new(() => + Assembly + .GetExecutingAssembly() + .GetTypes() + .Where( + t => + t.Namespace == typeof(OutputLocalization.Progress_BaseEventArgs).Namespace + && !t.IsAbstract + && t.GetMember(C_METHOD_TryParse, BindingFlags.Static | BindingFlags.Public).Any() + ) + .Select(t => (System.Reflection.MethodInfo)t.GetMember(C_METHOD_TryParse, BindingFlags.Static | BindingFlags.Public).First()) + .ToArray()); + + #endregion + + + public DateTime Timestamp { get; private set; } = DateTime.Now; + public readonly string RAWData = string.Empty; + + + public DataReceivedEventArgsEx(string data) : base() + { + this.RAWData = data; + } + + + public void UpdateTimestamp(DateTime newTimestamp) + { + Timestamp = newTimestamp; + RecalculateEstimation(); + } + + + protected virtual void RecalculateEstimation() { } + + + public override string ToString() => RAWData; + + + public static DataReceivedEventArgsEx Parse(DataReceivedEventArgs e) + { + string rawDada = e.Data; + +#if DEBUG + Debug.Write($"Parsing RAW '{rawDada}'... "); +#endif + DataReceivedEventArgsEx? dreax = null; + try + { + + var lop = _localizedOutputParsers.Value; + foreach (var miTryParse in lop) + { + var input = new object[] { rawDada, null }; + if ((bool)miTryParse.Invoke(null, input)) + { + dreax = (DataReceivedEventArgsEx)input[1]; + break; + } + } + + /* OLD + if (OutputLocalization.Header_CleaningPhyDiskEventArgs.TryParse(rawDada, out var hdr_pd)) + dreax = hdr_pd; + else if (OutputLocalization.Header_PassInfoEventArgs.TryParse(rawDada, out var hdr_pi)) + dreax = hdr_pi; + else if (OutputLocalization.Progress_VolumeFreeSpace_ZeroingFreeSpace.TryParse(rawDada, out var vol_pi)) + dreax = vol_pi; + else if (OutputLocalization.Progress_PhyDisk_ProgressEventArgs.TryParse(rawDada, out var pri)) + dreax = pri; + */ + + } + catch (Exception ex) + { +#if DEBUG + Debug.WriteLine($"*** ERROR DataReceivedEventArgsEx.Parse: {ex}"); +#endif + } + + dreax ??= new DataReceivedEventArgsEx(rawDada); +#if DEBUG + Debug.WriteLine(dreax.ToString()); +#endif + return dreax!; + } + } + + + + + +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Header_CleaningPhyDiskEventArgs.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Header_CleaningPhyDiskEventArgs.cs new file mode 100644 index 0000000..65b872a --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Header_CleaningPhyDiskEventArgs.cs @@ -0,0 +1,46 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + internal class Header_CleaningPhyDiskEventArgs : DataReceivedEventArgsEx + { + + private const string C_PREFIX = "Cleaning disk "; + + //Cleaning disk 6: + private static readonly Regex _rx = new(@"Cleaning \s disk \s (?\d+)\:", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + + + public readonly uint DiskNumber; + + + internal Header_CleaningPhyDiskEventArgs(string raw, uint passCount) : base(raw) => DiskNumber = passCount; + + + public static bool TryParse(string raw, out Header_CleaningPhyDiskEventArgs? piea) + { + piea = null; + + if (!raw.StartsWith(C_PREFIX, StringComparison.InvariantCultureIgnoreCase)) return false; + + Match? mx = _rx.Match(raw.Trim()); + if (!mx?.Success ?? false) return false; + + GroupCollection rGroups = mx!.Groups; + piea = new(raw, uint.Parse(rGroups["DiskNumber"].Value)); + return true; + } + + + public override string ToString() + { + string localizedFormat = Localization.Strings.M_OUTPUT_LOCALIZATION_PHY_DISK_NO; + + return localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(DiskNumber); + } + + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Header_PassInfoEventArgs.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Header_PassInfoEventArgs.cs new file mode 100644 index 0000000..430c694 --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Header_PassInfoEventArgs.cs @@ -0,0 +1,46 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + internal class Header_PassInfoEventArgs : DataReceivedEventArgsEx + { + + private const string C_PREFIX = "SDelete is set for "; + + //SDelete is set for 1 pass. + private static readonly Regex _rx = new(@".+ set \s for \s (?\d+) \s pass", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + + + public readonly uint PassCount; + + + internal Header_PassInfoEventArgs(string raw, uint passCount) : base(raw) => PassCount = passCount; + + + public static bool TryParse(string raw, out Header_PassInfoEventArgs? piea) + { + piea = null; + + if (!raw.StartsWith(C_PREFIX, StringComparison.InvariantCultureIgnoreCase)) return false; + + Match? mx = _rx.Match(raw.Trim()); + if (!mx?.Success ?? false) return false; + + GroupCollection rGroups = mx!.Groups; + piea = new(raw, uint.Parse(rGroups["PassCount"].Value)); + return true; + } + + + public override string ToString() + { + string localizedFormat = Localization.Strings.M_OUTPUT_LOCALIZATION_PASS_COUNT; + + return localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(PassCount); + } + + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_BaseEventArgs.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_BaseEventArgs.cs new file mode 100644 index 0000000..839c441 --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_BaseEventArgs.cs @@ -0,0 +1,12 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + internal abstract class Progress_BaseEventArgs : DataReceivedEventArgsEx + { + public readonly uint CurrentOperationProgressPercent; + + internal Progress_BaseEventArgs(string raw, uint currentOperationProgressPercent) : base(raw) + => CurrentOperationProgressPercent = currentOperationProgressPercent; + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_DirOrFile_Deleted.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_DirOrFile_Deleted.cs new file mode 100644 index 0000000..b6c122c --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_DirOrFile_Deleted.cs @@ -0,0 +1,42 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + + /* + T:\file.txt...deleted. + T:\folder...deleted. + */ + internal class Progress_DirOrFile_Deleted : DataReceivedEventArgsEx + { + private const string C_SUFFIX = "...deleted."; + + public readonly string FileSystemObject; + + + internal Progress_DirOrFile_Deleted(string raw, string fileSystemObject) : base(raw) + => FileSystemObject = fileSystemObject; + + + public static bool TryParse(string raw, out Progress_DirOrFile_Deleted? piea) + { + piea = null; + + if (!(raw.EndsWith(C_SUFFIX, StringComparison.InvariantCultureIgnoreCase) && (raw.Length >= C_SUFFIX.Length))) return false; + string fileSystemObject = raw.Substring(0, raw.Length - C_SUFFIX.Length); + + piea = new(raw, fileSystemObject); + return true; + } + + + public override string ToString() + { + string localizedFormat = Localization.Strings.M_OUTPUT_LOCALIZATION_FSO_DELETED; + + return localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(FileSystemObject); + } + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_PhyDisk_ProgressEventArgs.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_PhyDisk_ProgressEventArgs.cs new file mode 100644 index 0000000..f704408 --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_PhyDisk_ProgressEventArgs.cs @@ -0,0 +1,128 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + + //Pass 0 (step 1/3) progress: 92% (99.23 MB/s) + internal class Progress_PhyDisk_ProgressEventArgs : Progress_BaseEventArgs + { + private const string C_PREFIX = "Pass"; + + private static readonly Regex _rx + = new(@"^Pass\s(?\d+)\s (\(step \s (?\d+) \/ (?\d+) \)\s)? progress\:\s(?\d+)\%\s\((?\d+\.\d\d)\s(?\w+\/s)\)", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + + private const double ESTIMATION_MIN_PERCENT = 1d; + private const double ESTIMATION_MIN_SECONDS_SPENT = 5d; + //private string _estimated = string.Empty; + + public readonly uint PassNumber; + public readonly float SpeedValue; + public readonly string SpeedUnits; + + public readonly int StepCurrent; + public readonly int StepsTotal; + + + internal Progress_PhyDisk_ProgressEventArgs(string raw, uint passCount, uint currentOperationProgressPercent, float speedValue, string speedUnits, int stepCurrent, int stepsTotal) : base(raw, currentOperationProgressPercent) + { + PassNumber = passCount; + SpeedValue = speedValue; + SpeedUnits = speedUnits; + + StepCurrent = stepCurrent; + StepsTotal = stepsTotal; + } + + + public static bool TryParse(string raw, out Progress_PhyDisk_ProgressEventArgs? piea) + { + piea = null; + + + if (!raw.StartsWith(C_PREFIX, StringComparison.InvariantCultureIgnoreCase)) return false; + + //Parse Progress Value + Match? mx = _rx.Match(raw.Trim()); + if (!mx?.Success ?? false) return false; + + GroupCollection rGroups = mx!.Groups; + uint passNumber = uint.Parse(rGroups["PassCount"].Value) + 1; + uint progressPercent = uint.Parse(rGroups["PercentProgress"].Value); + + string speedString = rGroups["SpeedValue"].Value; + speedString = speedString.Replace(".", ","); + float speedValue = float.Parse(speedString, System.Globalization.NumberStyles.Float); + string speedUnits = rGroups["SpeedUnits"].Value ?? ""; + + int stepCurrent = rGroups.e_ParseRegexValueAsNumeric("StepCurrent", -1); + int stepsTotal = rGroups.e_ParseRegexValueAsNumeric("StepsTotal", -1); + + piea = new(raw, passNumber, progressPercent, speedValue, speedUnits, stepCurrent, stepsTotal); + return true; + } + + + private bool IsVersion_2_05_Output => (StepCurrent > 0 && StepsTotal > 0); + + public float TotalPercent + { + get + { + float p = CurrentOperationProgressPercent; + if (StepCurrent > 0 && StepsTotal > 1 && CurrentOperationProgressPercent > 0) + { + //for SDelete version 2.05: Recalculation total progress over all steps + float maxPercent = 100f * (float)StepsTotal; + float currentPercent = ((StepCurrent - 1) * 100f) + CurrentOperationProgressPercent; + p = (currentPercent / maxPercent) * 100f; + } + return p; + } + } + + protected override void RecalculateEstimation() + { + /* + _estimated = string.Empty; + + base.RecalculateEstimation(); + if (CurrentOperationProgressPercent < ESTIMATION_MIN_PERCENT || CurrentOperationProgressPercent >= 100d) return; + double timeSpent = (DateTime.Now - Timestamp).TotalSeconds; + if (timeSpent < ESTIMATION_MIN_SECONDS_SPENT) return; + + + double progressPercent = TotalProgress; + double progressPercentPerSecond = (progressPercent) / timeSpent; + double progressPercentLeave = (100d - progressPercent); + double dblSecondsLeave = (progressPercentLeave / progressPercentPerSecond).e_Round(0); + if (dblSecondsLeave < 1d) return; + + dblSecondsLeave *= 1000d; + + if (dblSecondsLeave <= (double)UInt32.MaxValue) + { + int iSecondsLeave = (int)dblSecondsLeave; + string sSecondsLeave = uom.WinAPI.Shell.StrFromTimeInterval(iSecondsLeave); + _estimated = $". {Localization.Strings.M_ESTIMATED}: {sSecondsLeave}"; + } + */ + } + + + /// Pass 0 progress: 20% (80.61 MB/s) + public override string ToString() + { + string localizedFormat = !IsVersion_2_05_Output + ? Localization.Strings.M_OUTPUT_LOCALIZATION_PROGRESS_PERCENT + : Localization.Strings.M_OUTPUT_LOCALIZATION_PROGRESS_PERCENT_2_05; + + //string progressPercent = CurrentOperationProgressPercent.ToString("N1").Trim(); + var s = localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(PassNumber, CurrentOperationProgressPercent, SpeedValue, SpeedUnits, StepCurrent, StepsTotal); + + return s;// + _estimated; + } + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_CleaningFreeSpace.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_CleaningFreeSpace.cs new file mode 100644 index 0000000..1d91ce7 --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_CleaningFreeSpace.cs @@ -0,0 +1,53 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + + //Cleaning free space on T:\: 1% + internal class Progress_VolumeFreeSpace_CleaningFreeSpace : Progress_BaseEventArgs + { + + private const string C_PREFIX = "Cleaning free space on "; + + private static readonly Regex _rx + = new(@"^Cleaning \s free \s space \s on \s (?.+) \:\s (?\d+)%", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + + + public readonly string VolumeName; + + internal Progress_VolumeFreeSpace_CleaningFreeSpace(string raw, string volumeName, uint currentOperationProgressPercent) : base(raw, currentOperationProgressPercent) + { + VolumeName = volumeName; + } + + + public static bool TryParse(string raw, out Progress_VolumeFreeSpace_CleaningFreeSpace? piea) + { + piea = null; + + + if (!raw.StartsWith(C_PREFIX, StringComparison.InvariantCultureIgnoreCase)) return false; + + Match? mx = _rx.Match(raw.Trim()); + if (!mx?.Success ?? false) return false; + + GroupCollection rGroups = mx!.Groups; + string volumeName = rGroups["VolumeName"].Value; + uint currentOperationProgressPercent = uint.Parse(rGroups["PercentProgress"].Value); + + piea = new(raw, volumeName, currentOperationProgressPercent); + return true; + } + + + public override string ToString() + { + string localizedFormat = Localization.Strings.M_OUTPUT_LOCALIZATION_VOLUME_CLEANING_PROGRESS; + + return localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(VolumeName, CurrentOperationProgressPercent); + } + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_CleaningMFT.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_CleaningMFT.cs new file mode 100644 index 0000000..f15dc14 --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_CleaningMFT.cs @@ -0,0 +1,66 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + + //Purging MFT files 4% complete + internal class Progress_VolumeFreeSpace_CleaningMFT : DataReceivedEventArgsEx + { + + /* +Cleaning MFT.../ +Cleaning MFT...- +Cleaning MFT...\ +Cleaning MFT...| +Cleaning MFT.../ +Cleaning MFT...- +Cleaning MFT...\ +Cleaning MFT...| + + */ + + private const string C_PREFIX = "Cleaning MFT..."; + + private static readonly Regex _rx + = new(@"^Cleaning \s MFT \.\.\. (?.{1})", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + + public readonly char ProgressChar; + + internal Progress_VolumeFreeSpace_CleaningMFT(string raw, char progressChar) : base(raw) + { + ProgressChar = progressChar; + } + + + public static bool TryParse(string raw, out Progress_VolumeFreeSpace_CleaningMFT? piea) + { + piea = null; + + + if (!raw.StartsWith(C_PREFIX, StringComparison.InvariantCultureIgnoreCase)) return false; + + //Parse Progress Value + Match? mx = _rx.Match(raw.Trim()); + if (!mx?.Success ?? false) return false; + + GroupCollection rGroups = mx!.Groups; + char progressChar = ' '; + string progressCharString = rGroups["ProgressChar"].Value; + if (progressCharString.e_IsNOTNullOrWhiteSpace()) progressChar = progressCharString[0]; + + piea = new(raw, progressChar); + return true; + } + + + public override string ToString() + { + string localizedFormat = Localization.Strings.M_OUTPUT_LOCALIZATION_VOLUME_CLEANING_MFT; + + return localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(ProgressChar); + } + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_PurgingMFTFiles.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_PurgingMFTFiles.cs new file mode 100644 index 0000000..62e32f9 --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_PurgingMFTFiles.cs @@ -0,0 +1,48 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + + //Purging MFT files 4% complete + internal class Progress_VolumeFreeSpace_PurgingMFTFiles : Progress_BaseEventArgs + { + + private const string C_PREFIX = "Purging MFT files "; + + private static readonly Regex _rx + = new(@"^Purging \s MFT \s files \s (?\d+)%", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + + + internal Progress_VolumeFreeSpace_PurgingMFTFiles(string raw, uint currentOperationProgressPercent) : base(raw, currentOperationProgressPercent) { } + + + public static bool TryParse(string raw, out Progress_VolumeFreeSpace_PurgingMFTFiles? piea) + { + piea = null; + + + if (!raw.StartsWith(C_PREFIX, StringComparison.InvariantCultureIgnoreCase)) return false; + + //Parse Progress Value + Match? mx = _rx.Match(raw.Trim()); + if (!mx?.Success ?? false) return false; + + GroupCollection rGroups = mx!.Groups; + uint currentOperationProgressPercent = uint.Parse(rGroups["PercentProgress"].Value); + + piea = new(raw, currentOperationProgressPercent); + return true; + } + + + public override string ToString() + { + string localizedFormat = Localization.Strings.M_OUTPUT_LOCALIZATION_VOLUME_PURGING_MFT_FILES; + + return localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(CurrentOperationProgressPercent); + } + } +} diff --git a/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_ZeroingFreeSpace.cs b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_ZeroingFreeSpace.cs new file mode 100644 index 0000000..4b8f2ca --- /dev/null +++ b/SDeleteGUI/Core/SDelete/OutputLocalization/Progress_VolumeFreeSpace_ZeroingFreeSpace.cs @@ -0,0 +1,53 @@ +#nullable enable + +namespace SDeleteGUI.Core.SDelete.OutputLocalization +{ + + //Zeroing free space on T:\: 0% + internal class Progress_VolumeFreeSpace_ZeroingFreeSpace : Progress_BaseEventArgs + { + + private const string C_PREFIX = "Zeroing free space on "; + + private static readonly Regex _rx + = new(@"^Zeroing \s free \s space \s on \s (?.+) \:\s (?\d+)%", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + + + public readonly string VolumeName; + + internal Progress_VolumeFreeSpace_ZeroingFreeSpace(string raw, string volumeName, uint progressPercent) : base(raw, progressPercent) + { + VolumeName = volumeName; + } + + + public static bool TryParse(string raw, out Progress_VolumeFreeSpace_ZeroingFreeSpace? piea) + { + piea = null; + + if (!raw.StartsWith(C_PREFIX, StringComparison.InvariantCultureIgnoreCase)) return false; + + //Parse Progress Value + Match? mx = _rx.Match(raw.Trim()); + if (!mx?.Success ?? false) return false; + + GroupCollection rGroups = mx!.Groups; + string volumeName = rGroups["VolumeName"].Value; + uint progressPercent = uint.Parse(rGroups["PercentProgress"].Value); + + piea = new(raw, volumeName, progressPercent); + return true; + } + + + public override string ToString() + { + string localizedFormat = Localization.Strings.M_OUTPUT_LOCALIZATION_VOLUME_ZEROING_PROGRESS; + + return localizedFormat.e_IsNullOrWhiteSpace() + ? RAWData + : localizedFormat.e_Format(VolumeName, CurrentOperationProgressPercent); + } + } +} diff --git a/SDeleteGUI/Core/SDelete/ProgressInfoEventArgs.cs b/SDeleteGUI/Core/SDelete/ProgressInfoEventArgs.cs deleted file mode 100644 index 58d1be4..0000000 --- a/SDeleteGUI/Core/SDelete/ProgressInfoEventArgs.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Text.RegularExpressions; - -#nullable enable - -namespace SDeleteGUI.Core.SDelete -{ - internal class ProgressInfoEventArgs : EventArgs - { - - //Pass 0 progress: 20 % (80.61 MB / s) - private static readonly Regex rexProgressPattern - = new(@"^Pass\s(?\d+)\sprogress\:\s(?\d+)\%\s\((?\d+\.\d\d)\s(?\w+\/s)\)$"); - - public readonly uint PassCount; - public readonly uint ProgressPercent; - public readonly float SpeedValue; - public readonly string SpeedUnits; - - - internal ProgressInfoEventArgs(string raw) : base() - { - Debug.Write($"Building ProgressInfo from RAW '{raw}'... "); - - /* - Pass 0 progress: 20% (80.61 MB/s) - Pass 0 progress: 20% (80.61 MB/s) - */ - - //Parse Progress Value - var mx = rexProgressPattern.Match(raw); - if (!mx.Success) throw new ArgumentOutOfRangeException($"Failed to parse progress value '{raw}'!"); - - //var aGroups = mx.GetGroupNames(); - var rGroups = mx.Groups; - PassCount = uint.Parse(rGroups["PassCount"].Value); - ProgressPercent = uint.Parse(rGroups["PercentProgress"].Value); - - string speedString = rGroups["SpeedValue"].Value; //string speedString = "80.60"; - speedString = speedString.Replace(".", ","); - SpeedValue = float.Parse(speedString, System.Globalization.NumberStyles.Float); - SpeedUnits = rGroups["SpeedUnits"].Value ?? ""; - - Debug.WriteLine(ToString()); - } - - public static bool IsMatch(string s) => rexProgressPattern.IsMatch(s); - - - /// Pass 0 progress: 20% (80.61 MB/s) - public override string ToString() => Localization.Strings.L_PROGRESS.e_Format(PassCount, ProgressPercent, SpeedValue, SpeedUnits); - } - - -} diff --git a/SDeleteGUI/Core/SDelete/SDeleteManager.cs b/SDeleteGUI/Core/SDelete/SDeleteManager.cs index ed0d1d7..ccbc49d 100644 --- a/SDeleteGUI/Core/SDelete/SDeleteManager.cs +++ b/SDeleteGUI/Core/SDelete/SDeleteManager.cs @@ -1,10 +1,6 @@ #nullable enable -using System.Runtime.InteropServices; - -using NLog; - using uom; @@ -59,66 +55,6 @@ sdelete [-p passes] [-z|-c] public event EventHandler Finished = delegate { }; - - internal class DataReceivedEventArgsEx : System.EventArgs - { - public DateTime Timestamp { get; private set; } = DateTime.Now; - - public readonly string Data = string.Empty; - - public readonly ProgressInfoEventArgs? ProgressInfo = null; - - private string estimated = string.Empty; - - - public DataReceivedEventArgsEx(string data) : base() - { - this.Data = data; - if (ProgressInfoEventArgs.IsMatch(Data)) ProgressInfo = new(Data); - } - public DataReceivedEventArgsEx(DataReceivedEventArgs e) : this(e.Data) { } - - public void UpdateTimestamp(DateTime newTimestamp) - { - Timestamp = newTimestamp; - RecalculateEstimation(); - } - - private const double ESTIMATION_MIN_PERCENT = 2d; - private const double ESTIMATION_MIN_SECONDS_SPENT = 5d; - - private void RecalculateEstimation() - { - estimated = string.Empty; - - if (ProgressInfo == null) return; - double progressPercent = ProgressInfo!.ProgressPercent; - - if (progressPercent < ESTIMATION_MIN_PERCENT || progressPercent >= 100d) return; - double timeSpent = (DateTime.Now - Timestamp).TotalSeconds; - if (timeSpent < ESTIMATION_MIN_SECONDS_SPENT) return; - - - double progressPercentPerSecond = ((double)ProgressInfo!.ProgressPercent) / timeSpent; - double progressPercentLeave = (100 - progressPercent); - double dblSecondsLeave = (progressPercentLeave / progressPercentPerSecond).e_Round(0); - if (dblSecondsLeave < 1d) return; - - dblSecondsLeave *= 1000; - - if (dblSecondsLeave <= (double)UInt32.MaxValue) - { - int iSecondsLeave = (int)dblSecondsLeave; - string sSecondsLeave = uom.WinAPI.Shell.StrFromTimeInterval(iSecondsLeave); - estimated = $". {Localization.Strings.L_ESTIMATED}: {sSecondsLeave}"; - } - } - - public override string ToString() => (ProgressInfo?.ToString() ?? Data) + estimated; - - } - - public event EventHandler OutputRAW = delegate { }; public event DataReceivedEventHandler Error = delegate { }; @@ -178,6 +114,9 @@ public SDeleteManager(Func binaryPathSpecifer) } + public uint Passes { get; private set; } + + /// Clean entrie Physical disk /// Make sure that the disk has no file system volumes! /// @@ -243,6 +182,8 @@ public void Run(uint passes, FileInfo[] filesToClean) private void StartSDeleteCore(uint passes, string SDeleteArgs, string? mutexName, string? resourceName) { + Passes = passes; + bool isNewMutex = false; Mutex? mtx = string.IsNullOrWhiteSpace(mutexName) ? null @@ -253,6 +194,7 @@ private void StartSDeleteCore(uint passes, string SDeleteArgs, string? mutexName if (null != mtx && !isNewMutex) throw new(C_RESOURCE_ALREADY_BUSY.e_Format(resourceName!)); SDeleteArgs = @$"{C_ARG_ACCEPT_LICENSE} {C_ARG_PASSES} {passes} " + SDeleteArgs; + //SDeleteArgs = @$"{C_ARG_PASSES} {passes} " + SDeleteArgs; _logger.Value.Debug($"Run_Clean: StartSDeleteCore. Passes '{passes}', SDeleteArgs = '{SDeleteArgs}'"); _runningProcess = null; @@ -308,7 +250,7 @@ private void StartSDeleteCore(uint passes, string SDeleteArgs, string? mutexName string cli = $"{SDeleteBinary.FullName} {SDeleteArgs}"; cli.e_SetClipboardSafe(); - DataReceivedEventArgsEx ea = new($"Starting: {cli}"); + DataReceivedEventArgsEx ea = new($"{Localization.Strings.M_STARING_SDELETE} {cli}"); OnCore_Data(this, ea); } catch @@ -337,20 +279,17 @@ private void OnCore_Data(object sender, DataReceivedEventArgs e) string s = (e.Data ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(s)) return; - DataReceivedEventArgsEx ea = new(e); - OnCore_Data(sender, ea); + OnCore_Data(sender, DataReceivedEventArgsEx.Parse(e)); } private void OnCore_Data(object sender, DataReceivedEventArgsEx e) { - _logger.Value.Debug($"OnCore_Data: '{e.Data}'"); - //if (null == OutputRAW) Debug.WriteLine($"WARNING! Unprocessed Output Data: '{s}'"); + _logger.Value.Debug($"OnCore_Data: '{e.RAWData}'"); OutputRAW.Invoke(sender, e); } private void OnCore_Error(object sender, DataReceivedEventArgs e) { _logger.Value.Debug($"OnCore_Error: '{e.Data}'"); - //if (e.Data == null) return; string s = (e.Data ?? string.Empty).Trim(); if (s.e_IsNullOrEmpty()) return; diff --git a/SDeleteGUI/Libs/uom.Core.Multiplatform.cs b/SDeleteGUI/Libs/uom.Core.Multiplatform.cs index 9c7df06..b9d5840 100644 --- a/SDeleteGUI/Libs/uom.Core.Multiplatform.cs +++ b/SDeleteGUI/Libs/uom.Core.Multiplatform.cs @@ -36,6 +36,7 @@ //Console.WriteLine("Visual Studio 7"); #endif +//if (args.Hyperlink.StartsWith("http:", StringComparison.InvariantCultureIgnoreCase)) #region Code Snippets @@ -499,6 +500,26 @@ private static int[] CreateInt32Array() #region SWITCH /* + * + object numericValue = Type.GetTypeCode(typeof(T)) switch + { + TypeCode.Int16 => Int16.Parse(stringValue, style), + TypeCode.Int32 => Int32.Parse(stringValue, style), + TypeCode.Int64 => Int64.Parse(stringValue, style), + + TypeCode.UInt16 => UInt16.Parse(stringValue, style), + TypeCode.UInt32 => UInt32.Parse(stringValue, style), + TypeCode.UInt64 => UInt64.Parse(stringValue, style), + + TypeCode.Decimal => Decimal.Parse(stringValue, style), + TypeCode.Double => Double.Parse(stringValue, style), + TypeCode.Single => Single.Parse(stringValue, style), + + TypeCode.Byte => Byte.Parse(stringValue, style), + + _ => defaultValue + }; + var ttt = direction switch { Direction.Up => Orientation.North, @@ -985,6 +1006,15 @@ End With #endregion #region ASYNC_AWAIT SAMPLE /* + IAsyncResult rAsincRslt = psInstance.BeginInvoke(); + void waitAsyncFinished() { while (rAsincRslt.IsCompleted == false) Thread.Sleep(500); } + await ((Action)waitAsyncFinished).e_StartAndWaitAsync(true); + PSDataCollection psResult = psInstance.EndInvoke(rAsincRslt); + + **** AWAIT with IAsyncResult + var result = await Task.Factory.FromAsync(psInstance.BeginInvoke(), psInstance.EndInvoke); + + * When yo do not need any task to run, just return Task.CompletedTask; @@ -1302,6 +1332,8 @@ private static async Task MainAsync(string[] args, CancellationToken cancellatio #endregion + + /// Commnon Tools For Net Multiplatform /// (C) UOM 2000-2023 namespace uom @@ -3414,7 +3446,32 @@ internal static T e_CheckRange(this T Value, T? MinLimit = default, T? MaxLim + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T e_ParseAsNumeric(this string stringValue, T defaultValue, NumberStyles style = NumberStyles.None) where T : struct + { + if (stringValue.e_IsNullOrWhiteSpace()) return defaultValue; + + object numericValue = Type.GetTypeCode(typeof(T)) switch + { + TypeCode.Int16 => Int16.Parse(stringValue, style), + TypeCode.Int32 => Int32.Parse(stringValue, style), + TypeCode.Int64 => Int64.Parse(stringValue, style), + + TypeCode.UInt16 => UInt16.Parse(stringValue, style), + TypeCode.UInt32 => UInt32.Parse(stringValue, style), + TypeCode.UInt64 => UInt64.Parse(stringValue, style), + + TypeCode.Decimal => Decimal.Parse(stringValue, style), + TypeCode.Double => Double.Parse(stringValue, style), + TypeCode.Single => Single.Parse(stringValue, style), + + TypeCode.Byte => Byte.Parse(stringValue, style), + _ => defaultValue + }; + + return (T)numericValue; + } @@ -4253,6 +4310,22 @@ internal static partial class Extensions_Conversions } + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class Extensions_RegEx + { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T e_ParseRegexValueAsNumeric(this GroupCollection g, string groupName, T defaultValue, NumberStyles style = NumberStyles.None) where T : struct + => (g[groupName].Value ?? "").e_ParseAsNumeric(defaultValue, style); + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T e_ParseRegexValueAsNumeric(this Match mx, string groupName, T defaultValue, NumberStyles style = NumberStyles.None) where T : struct + => mx.Groups.e_ParseRegexValueAsNumeric(groupName, defaultValue, style); + + } + [EditorBrowsable(EditorBrowsableState.Never)] internal static class Extensions_StringAndFormat { @@ -4874,19 +4947,20 @@ internal static bool e_Contains(this string SourceText, IEnumerable Find } #region Wrap - private const string CS_ESCAPE_LF = "\n"; + //private const string CS_ESCAPE_LF = "\n"; - /// Заменяет "\n" на VBCRLF + /// Replacing "\n" to Environment.NewLine [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static string e_WrapCPP(this string SourceText) => SourceText.Replace(@"\n", CS_ESCAPE_LF); + internal static string e_WrapCPP(this string SourceText) => SourceText.Replace(@"\n", Environment.NewLine); - /// Заменяет символ "|" на VBCRLF + /// Replacing "|" to Environment.NewLine [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static string e_WrapVB(this string SourceText) => SourceText.Replace('|'.ToString(), CS_ESCAPE_LF); + internal static string e_WrapVB(this string SourceText) => SourceText.Replace('|'.ToString(), Environment.NewLine); - /// Вызывает WrapCPP("\n"), затем WrapVB("|") на VBCRLF - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static string e_Wrap(this string SourceText) => SourceText.e_WrapVB().e_WrapCPP(); + /// Replacing "\n" or "|" to Environment.NewLine + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static string e_Wrap(this string SourceText) => SourceText.e_WrapVB().e_WrapCPP(); #endregion @@ -5664,6 +5738,15 @@ public static IEnumerable e_Sort(this IEnumerable source) where T : Sys return (from N in source orderby N select N).ToArray(); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string[] e_SortArrayOfStrings(this string[] source) + { + Array.Sort(source, StringComparer.InvariantCultureIgnoreCase); + return source; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T[] e_SortAsArray(this IEnumerable source) where T : System.IComparable => source.e_Sort().ToArray(); @@ -7249,8 +7332,7 @@ public static FileStream e_CreateStreamR(this string file, [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static FileStream e_CreateStreamR(this FileInfo fi, - FileMode fm = FileMode.Open, FileAccess fa = FileAccess.Read, FileShare fs = FileShare.ReadWrite) + public static FileStream e_CreateStreamR(this FileInfo fi, FileMode fm = FileMode.Open, FileAccess fa = FileAccess.Read, FileShare fs = FileShare.ReadWrite) => new(fi.FullName, fm, fa, fs); @@ -7337,13 +7419,17 @@ public static IEnumerable e_ReadLines(this string src, bool skipEmptyLin [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static IEnumerable e_ReadLines(this FileInfo fi, Encoding? encoding = null, bool skipEmptyLines = false) + internal static string[] e_ReadLines(this FileInfo fi, Encoding? encoding = null, bool skipEmptyLines = false) { - using var fs = fi.e_CreateStreamR(); - using var sr = new System.IO.StreamReader(fs, encoding ?? Encoding.Unicode); - return sr.e_ReadLines(skipEmptyLines); + using FileStream fs = fi.e_CreateStreamR(); + using StreamReader sr = new(fs, encoding ?? Encoding.Unicode); + return sr.e_ReadLines(skipEmptyLines).ToArray(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static async Task e_ReadLinesAsync(this FileInfo fi, Encoding? encoding = null, bool skipEmptyLines = false) + => await Task.Factory.StartNew(() => fi.e_ReadLines(encoding, skipEmptyLines), TaskCreationOptions.LongRunning); + #endregion @@ -7818,6 +7904,14 @@ internal static partial class Extensions_Async_MT { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static async Task e_StartAndWaitAsync(this Action a, bool longRunning) + { + using (Task tskWaitJobFinish = new(a, TaskCreationOptions.LongRunning)) + await tskWaitJobFinish.e_StartAndWaitAsync(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static async Task e_StartAndWaitAsync(this Task t) { @@ -7903,6 +7997,22 @@ internal static (bool result, Exception? ex) e_tryCatch(this Action a, Action? f finally { finallyAction?.Invoke(); } } + /// Exec FUNC. Return result + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static (bool result, Exception? ex) e_tryCatchWithErrorUI(this Action a) + { + try + { + a.Invoke(); + return (true, null); + } + catch (Exception ex) + { + ex.e_LogError(true); + return (false, ex); + } + } + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static T? e_tryCatch(this Func a, T? resultOnError = default, Action? finallyAction = null) @@ -7960,6 +8070,23 @@ internal static async Task e_WhenAll(this IEnumerable> aTasks, [EditorBrowsable(EditorBrowsableState.Never)] internal static partial class Extensions_DebugAndErrors { + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void e_trycatch(this Func operation, string errorMessageTemplate, params object[] messageArgs) + { + const uint S_OK = 0; + uint result = operation(); + if (result != S_OK) + { + string message = string.Format(errorMessageTemplate, messageArgs); + throw new Exception($"{message}. Error code: {result} (see WinError.h)"); + } + } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void DEBUG_SHOW_LINE(this string sMessage) => $"{sMessage} \r\n".DEBUG_SHOW(); diff --git a/SDeleteGUI/Libs/uom.Core.Win.cs b/SDeleteGUI/Libs/uom.Core.Win.cs index 3d9f5f3..313ace1 100644 --- a/SDeleteGUI/Libs/uom.Core.Win.cs +++ b/SDeleteGUI/Libs/uom.Core.Win.cs @@ -14,6 +14,7 @@ using static uom.MessageBoxWithCheckbox.MessageBox; using SaveFileDialog = System.Windows.Forms.SaveFileDialog; using OpenFileDialog = System.Windows.Forms.OpenFileDialog; +using System.Runtime.Remoting; #if NET5_0_OR_GREATER || NET6_0_OR_GREATER || NETCOREAPP3_0_OR_GREATER @@ -220,11 +221,27 @@ internal static void Delete(string name) keySetting?.Flush(); } - internal static T? Get_T( + internal static DateTime Get_DateTime( string name, - T? defaultValue = default, + DateTime defaultValue, bool searchAllVersions = true, Version? searchVersionBelowOrEqual = null) + { + long dtBinary = uom.AppTools.AppSettings.Get_T(name, 0L); + DateTime dt = (dtBinary == 0) + ? defaultValue + : DateTime.FromBinary(dtBinary); + + return dt; + } + + + + internal static T? Get_T( + string name, + T? defaultValue = default, + bool searchAllVersions = true, + Version? searchVersionBelowOrEqual = null) { RegistryKey keyVersionedSettings = OpenRegKey(); @@ -665,6 +682,9 @@ internal static void StartWinSysTool_MMC_lusrmgr() internal static void StartWinSysTool_MMC_devmgmt() => StartMMCProcess("devmgmt.msc", true, ThrowExceptionOnError: true); + internal static void StartWinSysTool_MMC_diskmgmt() + => StartMMCProcess("diskmgmt.msc", true, ThrowExceptionOnError: true); + #endregion #endregion @@ -3466,6 +3486,17 @@ public static ComboboxItemEnumContainer[] e_GetAllValuesAsEnumContainers(t //var eAA2 = typeof(XXX).EnumGetAllValuesArray } + public static T e_BuildFromFlags(this T initialValue, params (CheckBox flagCondition, T flagToSet)[] flags) where T : Enum + { + Int64 val = Convert.ToInt64(initialValue); + foreach (var item in flags) + { + if (item.flagCondition.Checked) val |= Convert.ToInt64(item.flagToSet); + } + T TResult = (T)Enum.ToObject(typeof(T), val); + return TResult; + } + } @@ -3533,7 +3564,10 @@ public static (Boolean ValueFound, RegistryValueKind Kind, T? Value) hRegKey.e_GetValueExt( ValueName, defaultValue, - (typeof(T) == typeof(string)) ? RegistryValueOptions.DoNotExpandEnvironmentNames : RegistryValueOptions.None); + (typeof(T) == typeof(string)) + ? RegistryValueOptions.DoNotExpandEnvironmentNames + : RegistryValueOptions.None + ); if (ValueFound && (null != Value)) return (true, Kind, (T)Value); } @@ -3546,6 +3580,10 @@ public static (Boolean ValueFound, RegistryValueKind Kind, T? Value) public static string? e_GetValue_String(this RegistryKey? hRegKey, string ValueName, string? DefaultValue = null) => hRegKey?.e_GetValueT(ValueName, DefaultValue).Value; + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string e_GetValue_StringOrEmpty(this RegistryKey? hRegKey, string ValueName, string? DefaultValue = null) => hRegKey?.e_GetValue_String(ValueName, DefaultValue) ?? string.Empty; @@ -3779,6 +3817,7 @@ public static void e_SetValue(this RegistryKey hRegKey, string name, T? value case uint data: valueToWrite = data; kind = RegistryValueKind.DWord; break; case ulong data: valueToWrite = data; kind = RegistryValueKind.QWord; break; case char data: valueToWrite = data; kind = RegistryValueKind.String; break; + case DateTime dt: valueToWrite = dt.ToBinary(); kind = RegistryValueKind.QWord; break; // float, double, decimal default: throw new ArgumentOutOfRangeException($"Unknown type of '{nameof(value)}' = '{typeof(T)}'"); @@ -5317,6 +5356,30 @@ public static void e_LimitRowsCountTo(this ListBox lst, int maxRows) while (lst.Items.Count >= maxRows) lst.Items.RemoveAt(0); }); } + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int e_LastItemIndex(this ListBox lst) => lst.Items.Count - 1; + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Object e_LastItem(this ListBox lst) => lst.Items[lst.e_LastItemIndex()]; + + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Object? e_SelectLastRow(this ListBox lst) + { + if (lst.Items.Count < 1) return null; + lst.SelectedIndex = (lst.e_LastItemIndex()); + return lst.SelectedItem; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void e_SetLastItem(this ListBox lst, object newValue) + => lst.Items[lst.e_LastItemIndex()] = newValue; + } @@ -25670,6 +25733,13 @@ internal static extern IntPtr SendMessage( [In] int wParam, [In, MarshalAs(UnmanagedType.LPTStr)] string? lParam); + [DllImport(core.WINDLL_USER, SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)] + internal static extern IntPtr SendMessage( + [In] IntPtr hwnd, + [In, MarshalAs(UnmanagedType.I4)] WindowMessages wMsg, + [In] int wParam, + [In] int lParam); + [DllImport(core.WINDLL_USER, SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)] internal static extern IntPtr SendMessage( diff --git a/SDeleteGUI/Libs/uom.Extensions_Autoupdater.NET.cs b/SDeleteGUI/Libs/uom.Extensions_Autoupdater.NET.cs new file mode 100644 index 0000000..9fac5cf --- /dev/null +++ b/SDeleteGUI/Libs/uom.Extensions_Autoupdater.NET.cs @@ -0,0 +1,36 @@ +#nullable enable + +using AutoUpdaterDotNET; + + +namespace uom.Extensions +{ + + /// + /// https://github.com/ravibpatel/AutoUpdater.NET + /// + internal static class Extensions_AutoUpdaterDotNET + { + + /* + Thread BackgroundThread = new(CheckForUpdates) { IsBackground = true }; + BackgroundThread.SetApartmentState(System.Threading.ApartmentState.STA); + BackgroundThread.Start(); + */ + + public static void e_StartAutoupdateOnShown(this Form f, string updaterXML, bool sync = true, bool runUpdateAsAdmin = false) + { + AutoUpdater.Synchronous = sync; + AutoUpdater.RunUpdateAsAdmin = false; + AutoUpdater.ShowSkipButton = false; + //AutoUpdater.SetOwner(this); + f.Shown += async (_, _) => await CheckForAppUpdates(updaterXML); + } + + private async static Task CheckForAppUpdates(string updaterXML) + { + void cbCkeckUpdates() { AutoUpdater.Start(updaterXML); } + await Task.Run(cbCkeckUpdates); + } + } +} \ No newline at end of file diff --git a/SDeleteGUI/Libs/uom.Extensions_NLog.cs b/SDeleteGUI/Libs/uom.Extensions_NLog.cs index c576c77..5755c81 100644 --- a/SDeleteGUI/Libs/uom.Extensions_NLog.cs +++ b/SDeleteGUI/Libs/uom.Extensions_NLog.cs @@ -169,6 +169,12 @@ public static void e_Debug(this Lazy log, string? message = null, [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) => log.Value.e_Debug(message, callerName, sourceFilePath, sourceLineNumber); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void e_Debug(this Lazy log, string? message = null, + [System.Runtime.CompilerServices.CallerMemberName] string callerName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) + => log.Value.e_Debug(message, callerName, sourceFilePath, sourceLineNumber); [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -185,6 +191,13 @@ public static void e_Warn(this Lazy log, string? message = null, [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) => log.Value.e_Warn(message, callerName, sourceFilePath, sourceLineNumber); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void e_Warn(this Lazy log, string? message = null, + [System.Runtime.CompilerServices.CallerMemberName] string callerName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) + => log.Value.e_Warn(message, callerName, sourceFilePath, sourceLineNumber); + [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -201,6 +214,12 @@ public static void e_Error(this Lazy log, Exception ex, [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) => log.Value.e_Error(ex, callerName, sourceFilePath, sourceLineNumber); + public static void e_Error(this Lazy log, Exception ex, + [System.Runtime.CompilerServices.CallerMemberName] string callerName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) + => log.Value.e_Error(ex, callerName, sourceFilePath, sourceLineNumber); + [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -217,6 +236,13 @@ public static void e_Fatal(this Lazy log, Exception ex, [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) => log.Value.e_Fatal(ex, callerName, sourceFilePath, sourceLineNumber); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void e_Fatal(this Lazy log, Exception ex, + [System.Runtime.CompilerServices.CallerMemberName] string callerName = "", + [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", + [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0) + => log.Value.e_Fatal(ex, callerName, sourceFilePath, sourceLineNumber); + diff --git a/SDeleteGUI/Localization/Strings.Designer.cs b/SDeleteGUI/Localization/Strings.Designer.cs index 4c05ed8..fb20019 100644 --- a/SDeleteGUI/Localization/Strings.Designer.cs +++ b/SDeleteGUI/Localization/Strings.Designer.cs @@ -133,7 +133,7 @@ internal static string L_CLEAN_TARGET_LOG_DISK_FREEE_SPACE { } /// - /// Looks up a localized string similar to Empty physical disk without partitions:. + /// Looks up a localized string similar to Empty disk without partitions:. /// internal static string L_CLEAN_TARGET_PHY_DISK { get { @@ -160,47 +160,56 @@ internal static string L_DONT_ASK_AGAIN { } /// - /// Looks up a localized string similar to {0} since the beginning. + /// Looks up a localized string similar to Free space cleaning method:. /// - internal static string L_ELAPSED { + internal static string L_FREE_SPACE_CLEAN_METHOD { get { - return ResourceManager.GetString("L_ELAPSED", resourceCulture); + return ResourceManager.GetString("L_FREE_SPACE_CLEAN_METHOD", resourceCulture); } } /// - /// Looks up a localized string similar to Estimated. + /// Looks up a localized string similar to Clean.. /// - internal static string L_ESTIMATED { + internal static string L_FREE_SPACE_CLEAN_METHOD_CLEAN { get { - return ResourceManager.GetString("L_ESTIMATED", resourceCulture); + return ResourceManager.GetString("L_FREE_SPACE_CLEAN_METHOD_CLEAN", resourceCulture); } } /// - /// Looks up a localized string similar to Free space cleaning method:. + /// Looks up a localized string similar to Zero (good for virtual disk optimization). /// - internal static string L_FREE_SPACE_CLEAN_METHOD { + internal static string L_FREE_SPACE_CLEAN_METHOD_ZERO { get { - return ResourceManager.GetString("L_FREE_SPACE_CLEAN_METHOD", resourceCulture); + return ResourceManager.GetString("L_FREE_SPACE_CLEAN_METHOD_ZERO", resourceCulture); } } /// - /// Looks up a localized string similar to Clean.. + /// Looks up a localized string similar to Tools. /// - internal static string L_FREE_SPACE_CLEAN_METHOD_CLEAN { + internal static string L_MNU_TOOLS { get { - return ResourceManager.GetString("L_FREE_SPACE_CLEAN_METHOD_CLEAN", resourceCulture); + return ResourceManager.GetString("L_MNU_TOOLS", resourceCulture); } } /// - /// Looks up a localized string similar to Zero (good for virtual disk optimization). + /// Looks up a localized string similar to Devices Manager. /// - internal static string L_FREE_SPACE_CLEAN_METHOD_ZERO { + internal static string L_MNU_TOOLS_DEV_MGMT { get { - return ResourceManager.GetString("L_FREE_SPACE_CLEAN_METHOD_ZERO", resourceCulture); + return ResourceManager.GetString("L_MNU_TOOLS_DEV_MGMT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Disk Management Console. + /// + internal static string L_MNU_TOOLS_DISK_MGMT { + get { + return ResourceManager.GetString("L_MNU_TOOLS_DISK_MGMT", resourceCulture); } } @@ -214,20 +223,20 @@ internal static string L_OUTPUT { } /// - /// Looks up a localized string similar to Overwrite Passes:. + /// Looks up a localized string similar to Compact. /// - internal static string L_OVERWRITE_PASS_COUNT { + internal static string L_OUTPUT_COMPACT { get { - return ResourceManager.GetString("L_OVERWRITE_PASS_COUNT", resourceCulture); + return ResourceManager.GetString("L_OUTPUT_COMPACT", resourceCulture); } } /// - /// Looks up a localized string similar to Pass {0}, progress: {1}% ({2} {3}). + /// Looks up a localized string similar to Overwrite Passes:. /// - internal static string L_PROGRESS { + internal static string L_OVERWRITE_PASS_COUNT { get { - return ResourceManager.GetString("L_PROGRESS", resourceCulture); + return ResourceManager.GetString("L_OVERWRITE_PASS_COUNT", resourceCulture); } } @@ -285,6 +294,33 @@ internal static string L_STOP { } } + /// + /// Looks up a localized string similar to Completed at {0}. + /// + internal static string M_COMPLETED_AT { + get { + return ResourceManager.GetString("M_COMPLETED_AT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} since the beginning. + /// + internal static string M_ELAPSED { + get { + return ResourceManager.GetString("M_ELAPSED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Estimated. + /// + internal static string M_ESTIMATED { + get { + return ResourceManager.GetString("M_ESTIMATED", resourceCulture); + } + } + /// /// Looks up a localized string similar to Loading disk list.... /// @@ -294,6 +330,96 @@ internal static string M_LOADING_DISK_LIST { } } + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_FSO_DELETED { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_FSO_DELETED", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_PASS_COUNT { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_PASS_COUNT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_PHY_DISK_NO { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_PHY_DISK_NO", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_PROGRESS_PERCENT { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_PROGRESS_PERCENT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_PROGRESS_PERCENT_2_05 { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_PROGRESS_PERCENT_2_05", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_VOLUME_CLEANING_MFT { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_VOLUME_CLEANING_MFT", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_VOLUME_CLEANING_PROGRESS { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_VOLUME_CLEANING_PROGRESS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_VOLUME_PURGING_MFT_FILES { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_VOLUME_PURGING_MFT_FILES", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string M_OUTPUT_LOCALIZATION_VOLUME_ZEROING_PROGRESS { + get { + return ResourceManager.GetString("M_OUTPUT_LOCALIZATION_VOLUME_ZEROING_PROGRESS", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Starting:. + /// + internal static string M_STARING_SDELETE { + get { + return ResourceManager.GetString("M_STARING_SDELETE", resourceCulture); + } + } + /// /// Looks up a localized string similar to Sysinternals '{0}' or '{1}' was not found in well-known locations! ///Do you want to find it manualy?. diff --git a/SDeleteGUI/Localization/Strings.resx b/SDeleteGUI/Localization/Strings.resx index f1801fa..b611de7 100644 --- a/SDeleteGUI/Localization/Strings.resx +++ b/SDeleteGUI/Localization/Strings.resx @@ -142,7 +142,7 @@ Logical drive (clean free space): - Empty physical disk without partitions: + Empty disk without partitions: partition(s) @@ -150,12 +150,6 @@ Don't ask me this again - - {0} since the beginning - - - Estimated - Free space cleaning method: @@ -165,15 +159,24 @@ Zero (good for virtual disk optimization) + + Tools + + + Devices Manager + + + Disk Management Console + Output: + + Compact + Overwrite Passes: - - Pass {0}, progress: {1}% ({2} {3}) - location: @@ -192,9 +195,48 @@ Stop + + Completed at {0} + + + {0} since the beginning + + + Estimated + Loading disk list... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Starting: + Sysinternals '{0}' or '{1}' was not found in well-known locations! Do you want to find it manualy? diff --git a/SDeleteGUI/Localization/Strings.ru.Designer.cs b/SDeleteGUI/Localization/Strings.ru.Designer.cs new file mode 100644 index 0000000..e69de29 diff --git a/SDeleteGUI/Localization/Strings.ru.resx b/SDeleteGUI/Localization/Strings.ru.resx index 7d3a733..2942bd4 100644 --- a/SDeleteGUI/Localization/Strings.ru.resx +++ b/SDeleteGUI/Localization/Strings.ru.resx @@ -142,7 +142,7 @@ Свободное место логического диска: - Чистый физический диск (без разделов) + Чистый диск (без разделов) разделов @@ -150,12 +150,6 @@ Не спрашивать больше - - {0} с начала - - - Осталось примерно - Способ очистки свободного пространства: @@ -165,15 +159,24 @@ Обнуление (оптимально для оптимизации виртуальных дисков) + + Инструменты + + + Диспетчер устройств + + + Управление дисками + Вывод: + + Сократить + Циклов перезаписи: - - Проход {0}, обработано: {1}% ({2} {3}) - расположено в: @@ -192,9 +195,48 @@ Остановить + + Завершено за {0} + + + {0} с начала + + + Осталось примерно + Загружается список дисков... + + '{0}' удалено. + + + Количество прходов {0}. + + + Очистка физического диска #{0}. + + + Проход {0}, обработано: {1}% ({2} {3}) + + + Проход {0} (этап {4}/{5}), обработано: {1}% ({2} {3}) + + + Очистка MFT {0}. + + + Очищаем свободное пространство на {0} {1}% + + + Очистка файлов MFT {0}% завершено. + + + Обнуляем свободное пространство на {0} {1}% + + + Запускаем: + Sysinternals '{0}' или '{1}' не найдена по общеизвестным расположениям! Хотите указать расположение вручную? diff --git a/SDeleteGUI/Properties/AssemblyInfo.cs b/SDeleteGUI/Properties/AssemblyInfo.cs index 945e72e..88fbfaf 100644 --- a/SDeleteGUI/Properties/AssemblyInfo.cs +++ b/SDeleteGUI/Properties/AssemblyInfo.cs @@ -10,5 +10,5 @@ [assembly: Guid("f3e32757-6d1a-464e-be43-1b0de8d66f56")] [assembly: AssemblyInformationalVersion("1.4.0.0")] -[assembly: AssemblyVersion("1.23.11.20")] -[assembly: AssemblyFileVersion("1.23.11.20")] +[assembly: AssemblyVersion("1.23.12.4")] +[assembly: AssemblyFileVersion("1.23.12.4")] diff --git a/SDeleteGUI/SDeleteGUI.csproj b/SDeleteGUI/SDeleteGUI.csproj index c4fc393..186cf18 100644 --- a/SDeleteGUI/SDeleteGUI.csproj +++ b/SDeleteGUI/SDeleteGUI.csproj @@ -56,16 +56,33 @@ - - + + 1.8.4 + + + 4.5.0 - + PreserveNewest + + Libs\SaveFileDialog.cs + Form + + + + + + + + + + + @@ -73,7 +90,7 @@ - + @@ -98,6 +115,11 @@ True Strings.resx + + True + True + Strings.ru.resx + diff --git "a/SDeleteGUI/UOM_SDeleteGUI - \320\257\321\200\320\273\321\213\320\272.lnk" "b/SDeleteGUI/UOM_SDeleteGUI - \320\257\321\200\320\273\321\213\320\272.lnk" new file mode 100644 index 0000000..e880518 Binary files /dev/null and "b/SDeleteGUI/UOM_SDeleteGUI - \320\257\321\200\320\273\321\213\320\272.lnk" differ diff --git a/SDeleteGUI/frmMain.Designer.cs b/SDeleteGUI/frmMain.Designer.cs index e403bab..bd2e289 100644 --- a/SDeleteGUI/frmMain.Designer.cs +++ b/SDeleteGUI/frmMain.Designer.cs @@ -33,7 +33,7 @@ private void InitializeComponent() this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain)); this.tlpParams = new System.Windows.Forms.TableLayoutPanel(); - this.label4 = new System.Windows.Forms.Label(); + this.lblCleanMode = new System.Windows.Forms.Label(); this.lblOverwritePassCount = new System.Windows.Forms.Label(); this.llSDeleteBinPath = new System.Windows.Forms.LinkLabel(); this.numPasses = new System.Windows.Forms.NumericUpDown(); @@ -60,14 +60,22 @@ private void InitializeComponent() this.tlpDown = new System.Windows.Forms.TableLayoutPanel(); this.lstLog = new SDeleteGUI.Core.ListBoxEx(); this.lblStatus = new System.Windows.Forms.Label(); - this.label1 = new System.Windows.Forms.Label(); + this.lblOutput = new System.Windows.Forms.Label(); + this.chkCompactOutput = new System.Windows.Forms.CheckBox(); this.tmrElapsed = new System.Windows.Forms.Timer(this.components); this.enableOnCheck = new uom.controls.Extenders.CheckBoxEnabler(this.components); + this.mnuMain = new System.Windows.Forms.MenuStrip(); + this.mnuTools = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuTools_DevMgmt = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuTools_DiskMgmt = new System.Windows.Forms.ToolStripMenuItem(); + this.pnlMain = new System.Windows.Forms.Panel(); this.tlpParams.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.numPasses)).BeginInit(); this.tlpCleanFreeSpaceMethods.SuspendLayout(); this.tlpDown.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.enableOnCheck)).BeginInit(); + this.mnuMain.SuspendLayout(); + this.pnlMain.SuspendLayout(); this.SuspendLayout(); // // tlpParams @@ -79,7 +87,7 @@ private void InitializeComponent() this.tlpParams.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tlpParams.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tlpParams.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 39F)); - this.tlpParams.Controls.Add(this.label4, 0, 9); + this.tlpParams.Controls.Add(this.lblCleanMode, 0, 9); this.tlpParams.Controls.Add(this.lblOverwritePassCount, 0, 8); this.tlpParams.Controls.Add(this.llSDeleteBinPath, 0, 0); this.tlpParams.Controls.Add(this.numPasses, 2, 8); @@ -98,7 +106,7 @@ private void InitializeComponent() this.tlpParams.Controls.Add(this.cboSource_LogDisk, 2, 4); this.tlpParams.Controls.Add(this.btnSource_Refresh, 3, 3); this.tlpParams.Dock = System.Windows.Forms.DockStyle.Top; - this.tlpParams.Location = new System.Drawing.Point(21, 22); + this.tlpParams.Location = new System.Drawing.Point(16, 16); this.tlpParams.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.tlpParams.Name = "tlpParams"; this.tlpParams.RowCount = 10; @@ -112,21 +120,21 @@ private void InitializeComponent() this.tlpParams.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpParams.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tlpParams.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpParams.Size = new System.Drawing.Size(1094, 300); + this.tlpParams.Size = new System.Drawing.Size(846, 300); this.tlpParams.TabIndex = 1; // - // label4 + // lblCleanMode // - this.label4.AutoSize = true; - this.tlpParams.SetColumnSpan(this.label4, 2); - this.label4.Dock = System.Windows.Forms.DockStyle.Fill; - this.label4.Location = new System.Drawing.Point(4, 256); - this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(315, 44); - this.label4.TabIndex = 0; - this.label4.Text = "Free space cleaning method:"; - this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.lblCleanMode.AutoSize = true; + this.tlpParams.SetColumnSpan(this.lblCleanMode, 2); + this.lblCleanMode.Dock = System.Windows.Forms.DockStyle.Fill; + this.lblCleanMode.Location = new System.Drawing.Point(4, 256); + this.lblCleanMode.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.lblCleanMode.Name = "lblCleanMode"; + this.lblCleanMode.Size = new System.Drawing.Size(315, 44); + this.lblCleanMode.TabIndex = 0; + this.lblCleanMode.Text = "Free space cleaning method:"; + this.lblCleanMode.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // lblOverwritePassCount // @@ -150,7 +158,7 @@ private void InitializeComponent() this.llSDeleteBinPath.Location = new System.Drawing.Point(4, 0); this.llSDeleteBinPath.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.llSDeleteBinPath.Name = "llSDeleteBinPath"; - this.llSDeleteBinPath.Size = new System.Drawing.Size(1086, 24); + this.llSDeleteBinPath.Size = new System.Drawing.Size(838, 24); this.llSDeleteBinPath.TabIndex = 0; this.llSDeleteBinPath.TabStop = true; this.llSDeleteBinPath.Text = "SDelete binary location:"; @@ -161,24 +169,24 @@ private void InitializeComponent() this.numPasses.Location = new System.Drawing.Point(327, 225); this.numPasses.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.numPasses.Maximum = new decimal(new int[] { - 10, - 0, - 0, - 0}); + 10, + 0, + 0, + 0}); this.numPasses.Minimum = new decimal(new int[] { - 1, - 0, - 0, - 0}); + 1, + 0, + 0, + 0}); this.numPasses.Name = "numPasses"; this.numPasses.Size = new System.Drawing.Size(94, 26); this.numPasses.TabIndex = 1; this.numPasses.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.numPasses.Value = new decimal(new int[] { - 1, - 0, - 0, - 0}); + 1, + 0, + 0, + 0}); // // optSource_Dir // @@ -209,7 +217,7 @@ private void InitializeComponent() this.tlpCleanFreeSpaceMethods.Name = "tlpCleanFreeSpaceMethods"; this.tlpCleanFreeSpaceMethods.RowCount = 1; this.tlpCleanFreeSpaceMethods.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tlpCleanFreeSpaceMethods.Size = new System.Drawing.Size(763, 34); + this.tlpCleanFreeSpaceMethods.Size = new System.Drawing.Size(515, 34); this.tlpCleanFreeSpaceMethods.TabIndex = 12; // // optCleanMode_Clean @@ -261,7 +269,7 @@ private void InitializeComponent() this.txtSource_Dir.Location = new System.Drawing.Point(327, 140); this.txtSource_Dir.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.txtSource_Dir.Name = "txtSource_Dir"; - this.txtSource_Dir.Size = new System.Drawing.Size(724, 26); + this.txtSource_Dir.Size = new System.Drawing.Size(476, 26); this.txtSource_Dir.TabIndex = 8; // // txtSource_Files @@ -273,7 +281,7 @@ private void InitializeComponent() this.txtSource_Files.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.txtSource_Files.Name = "txtSource_Files"; this.txtSource_Files.ReadOnly = true; - this.txtSource_Files.Size = new System.Drawing.Size(724, 26); + this.txtSource_Files.Size = new System.Drawing.Size(476, 26); this.txtSource_Files.TabIndex = 10; // // lblWhatToClean @@ -284,14 +292,14 @@ private void InitializeComponent() this.lblWhatToClean.Location = new System.Drawing.Point(4, 39); this.lblWhatToClean.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.lblWhatToClean.Name = "lblWhatToClean"; - this.lblWhatToClean.Size = new System.Drawing.Size(1086, 20); + this.lblWhatToClean.Size = new System.Drawing.Size(838, 20); this.lblWhatToClean.TabIndex = 1; this.lblWhatToClean.Text = "What to clean:"; // // btnSource_DisplaySelectionUI // this.btnSource_DisplaySelectionUI.Dock = System.Windows.Forms.DockStyle.Fill; - this.btnSource_DisplaySelectionUI.Location = new System.Drawing.Point(1059, 140); + this.btnSource_DisplaySelectionUI.Location = new System.Drawing.Point(811, 140); this.btnSource_DisplaySelectionUI.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.btnSource_DisplaySelectionUI.Name = "btnSource_DisplaySelectionUI"; this.tlpParams.SetRowSpan(this.btnSource_DisplaySelectionUI, 2); @@ -308,7 +316,7 @@ private void InitializeComponent() this.panel1.Location = new System.Drawing.Point(4, 212); this.panel1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(1086, 3); + this.panel1.Size = new System.Drawing.Size(838, 3); this.panel1.TabIndex = 4; // // pnlSeparetor1 @@ -319,7 +327,7 @@ private void InitializeComponent() this.pnlSeparetor1.Location = new System.Drawing.Point(4, 29); this.pnlSeparetor1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.pnlSeparetor1.Name = "pnlSeparetor1"; - this.pnlSeparetor1.Size = new System.Drawing.Size(1086, 5); + this.pnlSeparetor1.Size = new System.Drawing.Size(838, 5); this.pnlSeparetor1.TabIndex = 9; // // optSource_PhyDisk @@ -345,7 +353,7 @@ private void InitializeComponent() this.cboSource_PhyDisk.Location = new System.Drawing.Point(327, 64); this.cboSource_PhyDisk.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.cboSource_PhyDisk.Name = "cboSource_PhyDisk"; - this.cboSource_PhyDisk.Size = new System.Drawing.Size(724, 28); + this.cboSource_PhyDisk.Size = new System.Drawing.Size(476, 28); this.cboSource_PhyDisk.TabIndex = 3; // // optSource_LogDisk @@ -369,14 +377,14 @@ private void InitializeComponent() this.cboSource_LogDisk.Location = new System.Drawing.Point(327, 102); this.cboSource_LogDisk.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.cboSource_LogDisk.Name = "cboSource_LogDisk"; - this.cboSource_LogDisk.Size = new System.Drawing.Size(724, 28); + this.cboSource_LogDisk.Size = new System.Drawing.Size(476, 28); this.cboSource_LogDisk.TabIndex = 5; // // btnSource_Refresh // this.btnSource_Refresh.Dock = System.Windows.Forms.DockStyle.Fill; this.btnSource_Refresh.Font = new System.Drawing.Font("Segoe UI", 12F); - this.btnSource_Refresh.Location = new System.Drawing.Point(1059, 64); + this.btnSource_Refresh.Location = new System.Drawing.Point(811, 64); this.btnSource_Refresh.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.btnSource_Refresh.Name = "btnSource_Refresh"; this.tlpParams.SetRowSpan(this.btnSource_Refresh, 2); @@ -389,10 +397,10 @@ private void InitializeComponent() // this.llShellRegister.AutoSize = true; this.llShellRegister.Dock = System.Windows.Forms.DockStyle.Top; - this.llShellRegister.Location = new System.Drawing.Point(4, 375); + this.llShellRegister.Location = new System.Drawing.Point(4, 254); this.llShellRegister.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.llShellRegister.Name = "llShellRegister"; - this.llShellRegister.Size = new System.Drawing.Size(921, 20); + this.llShellRegister.Size = new System.Drawing.Size(673, 20); this.llShellRegister.TabIndex = 13; this.llShellRegister.TabStop = true; this.llShellRegister.Text = "*"; @@ -406,23 +414,23 @@ private void InitializeComponent() this.pnlSeparator3.Location = new System.Drawing.Point(4, 5); this.pnlSeparator3.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.pnlSeparator3.Name = "pnlSeparator3"; - this.pnlSeparator3.Size = new System.Drawing.Size(1086, 5); + this.pnlSeparator3.Size = new System.Drawing.Size(838, 5); this.pnlSeparator3.TabIndex = 22; // // pbProgress // this.tlpDown.SetColumnSpan(this.pbProgress, 2); this.pbProgress.Dock = System.Windows.Forms.DockStyle.Top; - this.pbProgress.Location = new System.Drawing.Point(4, 321); + this.pbProgress.Location = new System.Drawing.Point(4, 200); this.pbProgress.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.pbProgress.Name = "pbProgress"; - this.pbProgress.Size = new System.Drawing.Size(1086, 11); + this.pbProgress.Size = new System.Drawing.Size(838, 11); this.pbProgress.TabIndex = 25; // // btnStartStop // this.btnStartStop.Dock = System.Windows.Forms.DockStyle.Fill; - this.btnStartStop.Location = new System.Drawing.Point(933, 343); + this.btnStartStop.Location = new System.Drawing.Point(685, 222); this.btnStartStop.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.btnStartStop.Name = "btnStartStop"; this.tlpDown.SetRowSpan(this.btnStartStop, 2); @@ -440,11 +448,12 @@ private void InitializeComponent() this.tlpDown.Controls.Add(this.btnStartStop, 1, 5); this.tlpDown.Controls.Add(this.lstLog, 0, 2); this.tlpDown.Controls.Add(this.lblStatus, 0, 5); - this.tlpDown.Controls.Add(this.label1, 0, 1); + this.tlpDown.Controls.Add(this.lblOutput, 0, 1); this.tlpDown.Controls.Add(this.pnlSeparator3, 0, 0); this.tlpDown.Controls.Add(this.llShellRegister, 0, 6); + this.tlpDown.Controls.Add(this.chkCompactOutput, 1, 1); this.tlpDown.Dock = System.Windows.Forms.DockStyle.Fill; - this.tlpDown.Location = new System.Drawing.Point(21, 322); + this.tlpDown.Location = new System.Drawing.Point(16, 316); this.tlpDown.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.tlpDown.Name = "tlpDown"; this.tlpDown.RowCount = 7; @@ -455,7 +464,8 @@ private void InitializeComponent() this.tlpDown.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 22F)); this.tlpDown.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 37F)); this.tlpDown.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); - this.tlpDown.Size = new System.Drawing.Size(1094, 400); + this.tlpDown.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tlpDown.Size = new System.Drawing.Size(846, 279); this.tlpDown.TabIndex = 1; // // lstLog @@ -464,49 +474,105 @@ private void InitializeComponent() this.lstLog.Dock = System.Windows.Forms.DockStyle.Fill; this.lstLog.IntegralHeight = false; this.lstLog.ItemHeight = 20; - this.lstLog.Location = new System.Drawing.Point(4, 40); + this.lstLog.Location = new System.Drawing.Point(4, 50); this.lstLog.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.lstLog.Name = "lstLog"; - this.lstLog.Size = new System.Drawing.Size(1086, 260); + this.lstLog.Size = new System.Drawing.Size(838, 129); this.lstLog.TabIndex = 1; // // lblStatus // this.lblStatus.AutoSize = true; this.lblStatus.Dock = System.Windows.Forms.DockStyle.Top; - this.lblStatus.Location = new System.Drawing.Point(4, 338); + this.lblStatus.Location = new System.Drawing.Point(4, 217); this.lblStatus.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.lblStatus.Name = "lblStatus"; - this.lblStatus.Size = new System.Drawing.Size(921, 20); + this.lblStatus.Size = new System.Drawing.Size(673, 20); this.lblStatus.TabIndex = 26; this.lblStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(4, 15); - this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(62, 20); - this.label1.TabIndex = 0; - this.label1.Text = "Output:"; + // lblOutput + // + this.lblOutput.AutoSize = true; + this.lblOutput.Location = new System.Drawing.Point(4, 15); + this.lblOutput.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.lblOutput.Name = "lblOutput"; + this.lblOutput.Size = new System.Drawing.Size(62, 20); + this.lblOutput.TabIndex = 0; + this.lblOutput.Text = "Output:"; + // + // chkCompactOutput + // + this.chkCompactOutput.AutoSize = true; + this.chkCompactOutput.Checked = true; + this.chkCompactOutput.CheckState = System.Windows.Forms.CheckState.Checked; + this.chkCompactOutput.Dock = System.Windows.Forms.DockStyle.Right; + this.chkCompactOutput.Location = new System.Drawing.Point(730, 18); + this.chkCompactOutput.Name = "chkCompactOutput"; + this.chkCompactOutput.Size = new System.Drawing.Size(113, 24); + this.chkCompactOutput.TabIndex = 27; + this.chkCompactOutput.Text = "checkBox1"; + this.chkCompactOutput.UseVisualStyleBackColor = true; // // tmrElapsed // this.tmrElapsed.Interval = 1000; // + // mnuMain + // + this.mnuMain.GripMargin = new System.Windows.Forms.Padding(2, 2, 0, 2); + this.mnuMain.ImageScalingSize = new System.Drawing.Size(24, 24); + this.mnuMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuTools}); + this.mnuMain.Location = new System.Drawing.Point(0, 0); + this.mnuMain.Name = "mnuMain"; + this.mnuMain.Size = new System.Drawing.Size(878, 33); + this.mnuMain.TabIndex = 2; + this.mnuMain.Text = "menuStrip1"; + // + // mnuTools + // + this.mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuTools_DevMgmt, + this.mnuTools_DiskMgmt}); + this.mnuTools.Name = "mnuTools"; + this.mnuTools.Size = new System.Drawing.Size(50, 29); + this.mnuTools.Text = "Tol"; + // + // mnuTools_DevMgmt + // + this.mnuTools_DevMgmt.Name = "mnuTools_DevMgmt"; + this.mnuTools_DevMgmt.Size = new System.Drawing.Size(148, 34); + this.mnuTools_DevMgmt.Text = "Dev"; + // + // mnuTools_DiskMgmt + // + this.mnuTools_DiskMgmt.Name = "mnuTools_DiskMgmt"; + this.mnuTools_DiskMgmt.Size = new System.Drawing.Size(148, 34); + this.mnuTools_DiskMgmt.Text = "Disk"; + // + // pnlMain + // + this.pnlMain.Controls.Add(this.tlpDown); + this.pnlMain.Controls.Add(this.tlpParams); + this.pnlMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.pnlMain.Location = new System.Drawing.Point(0, 33); + this.pnlMain.Name = "pnlMain"; + this.pnlMain.Padding = new System.Windows.Forms.Padding(16); + this.pnlMain.Size = new System.Drawing.Size(878, 611); + this.pnlMain.TabIndex = 3; + // // frmMain // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1136, 744); - this.Controls.Add(this.tlpDown); - this.Controls.Add(this.tlpParams); + this.ClientSize = new System.Drawing.Size(878, 644); + this.Controls.Add(this.pnlMain); + this.Controls.Add(this.mnuMain); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); - this.MinimumSize = new System.Drawing.Size(800, 800); + this.MinimumSize = new System.Drawing.Size(800, 600); this.Name = "frmMain"; - this.Padding = new System.Windows.Forms.Padding(21, 22, 21, 22); this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "frmMain"; this.tlpParams.ResumeLayout(false); @@ -517,6 +583,10 @@ private void InitializeComponent() this.tlpDown.ResumeLayout(false); this.tlpDown.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.enableOnCheck)).EndInit(); + this.mnuMain.ResumeLayout(false); + this.mnuMain.PerformLayout(); + this.pnlMain.ResumeLayout(false); + this.pnlMain.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -539,7 +609,7 @@ private void InitializeComponent() private RadioButton optCleanMode_Zero; private RadioButton optCleanMode_Clean; private TableLayoutPanel tlpCleanFreeSpaceMethods; - private Label label4; + private Label lblCleanMode; private RadioButton optSource_PhyDisk; private ComboBox cboSource_PhyDisk; private Button btnStartStop; @@ -552,8 +622,14 @@ private void InitializeComponent() private Panel pnlSeparator3; private Label lblStatus; private System.Windows.Forms.Timer tmrElapsed; - private Label label1; + private Label lblOutput; private LinkLabel llShellRegister; private uom.controls.Extenders.CheckBoxEnabler enableOnCheck; + private CheckBox chkCompactOutput; + private MenuStrip mnuMain; + private ToolStripMenuItem mnuTools; + private ToolStripMenuItem mnuTools_DiskMgmt; + private Panel pnlMain; + private ToolStripMenuItem mnuTools_DevMgmt; } } \ No newline at end of file diff --git a/SDeleteGUI/frmMain.cs b/SDeleteGUI/frmMain.cs index fb303b0..6750912 100644 --- a/SDeleteGUI/frmMain.cs +++ b/SDeleteGUI/frmMain.cs @@ -12,6 +12,8 @@ using static System.Windows.Forms.LinkLabel; using static SDeleteGUI.Core.SDelete.SDeleteManager; +using OpenFileDialog = System.Windows.Forms.OpenFileDialog; + namespace SDeleteGUI { @@ -21,6 +23,7 @@ internal partial class frmMain : Form private static string C_LOADING_DISKS_LIST = Localization.Strings.M_LOADING_DISK_LIST; private static string C_ASK_USER = string.Format(Localization.Strings.Q_MANUAL_SEARCH_SDELETE_BINARY, SDeleteManager.C_SDBIN_FILE64, SDeleteManager.C_SDBIN_FILE); + private enum SourceModes : int { Unknown = 0, @@ -36,10 +39,11 @@ private enum SourceModes : int private SDeleteManager? _sdmgr = null; private bool _isRunning = false; - private RadioButton[] _optSources = { }; + private RadioButton[] _optSources = []; private Lazy _logger = new(() => LogManager.GetCurrentClassLogger()); + public frmMain() { InitializeComponent(); @@ -50,10 +54,10 @@ public frmMain() this.Shown += (_, _) => _Shown(); this.FormClosing += (s, e) => { - _logger.Value.Debug($"FormClosing, CloseReason = {e.CloseReason}"); + _logger.e_Debug($"FormClosing, CloseReason = {e.CloseReason}"); if (e.CloseReason == CloseReason.UserClosing && _isRunning) { - string msg = Localization.Strings.Q_STOP_ACTIVE_CLEANUP; + string msg = Localization.Strings.Q_STOP_ACTIVE_CLEANUP.e_WrapCPP(); if (MessageBox.Show(msg, Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) { e.Cancel = true; @@ -63,11 +67,9 @@ public frmMain() } }; + #region Source Params - _optSources = new RadioButton[] { optSource_PhyDisk, optSource_LogDisk, optSource_Dir, optSource_Files }; - - llSDeleteBinPath.LinkClicked += OnSDBinary_LinkClicked; - llShellRegister.LinkClicked += (_, _) => OnShellRegister_Click(); + _optSources = [optSource_PhyDisk, optSource_LogDisk, optSource_Dir, optSource_Files]; optSource_PhyDisk.CheckedChanged += (_, _) => OnSourceChanged(); optSource_LogDisk.CheckedChanged += (_, _) => OnSourceChanged(); @@ -76,21 +78,34 @@ public frmMain() btnSource_Refresh.Click += async (_, _) => await OnSource_RefreshLists(); btnSource_DisplaySelectionUI.Click += (_, _) => OnSource_DisplaySelectionUI(); - txtSource_Files.Click += (_, _) => OnSource_DisplaySelectionUI(); - cboSource_PhyDisk.SelectedIndexChanged += (_, _) => UpdateUI(); + + txtSource_Dir.Click += (_, _) => OnSource_DisplaySelectionUI(); txtSource_Dir.TextChanged += (_, _) => UpdateUI(); + txtSource_Files.Click += (_, _) => OnSource_DisplaySelectionUI(); txtSource_Files.TextChanged += (_, _) => UpdateUI(); - btnStartStop.Click += (_, _) => OnStartStop(); + #endregion + btnStartStop.Click += (_, _) => OnStartStop(); tmrElapsed.Tick += (_, _) => OnElapsedTimerTick(); + + mnuTools_DevMgmt.Click += (_, _) => ((Action)uom.AppTools.StartWinSysTool_MMC_devmgmt).e_tryCatchWithErrorUI(); + mnuTools_DiskMgmt.Click += (_, _) => ((Action)uom.AppTools.StartWinSysTool_MMC_diskmgmt).e_tryCatchWithErrorUI(); + + llSDeleteBinPath.LinkClicked += OnSDBinary_LinkClicked; + llShellRegister.LinkClicked += (_, _) => OnShellRegister_Click(); } + private void LocalizeUI() { Text = $"{Application.ProductName} {Assembly.GetExecutingAssembly().GetName().Version}"; + mnuTools.Text = Localization.Strings.L_MNU_TOOLS; + mnuTools_DevMgmt.Text = Localization.Strings.L_MNU_TOOLS_DEV_MGMT; + mnuTools_DiskMgmt.Text = Localization.Strings.L_MNU_TOOLS_DISK_MGMT; + btnSource_DisplaySelectionUI.Text = "..."; btnSource_Refresh.Text = "🗘"; @@ -102,31 +117,28 @@ private void LocalizeUI() optSource_Dir.Text = Localization.Strings.L_CLEAN_TARGET_FOLDER; optSource_Files.Text = Localization.Strings.L_CLEAN_TARGET_FILES; - label4.Text = Localization.Strings.L_FREE_SPACE_CLEAN_METHOD; + lblCleanMode.Text = Localization.Strings.L_FREE_SPACE_CLEAN_METHOD; optCleanMode_Clean.Text = Localization.Strings.L_FREE_SPACE_CLEAN_METHOD_CLEAN; optCleanMode_Zero.Text = Localization.Strings.L_FREE_SPACE_CLEAN_METHOD_ZERO.e_Wrap(); lblOverwritePassCount.Text = Localization.Strings.L_OVERWRITE_PASS_COUNT; btnStartStop.Text = Localization.Strings.L_START; - label1.Text = Localization.Strings.L_OUTPUT; + lblOutput.Text = Localization.Strings.L_OUTPUT; + chkCompactOutput.Text = Localization.Strings.L_OUTPUT_COMPACT; } - - - - private async Task _Load() { - _logger.Value.Debug("_Load"); + _logger.e_Debug("_Load"); FileInfo cbAskUserForBinary() { - _logger.Value.Debug(C_ASK_USER); + _logger.e_Debug(C_ASK_USER); if (!C_ASK_USER.e_MsgboxAskIsYes(false, Application.ProductName)) throw new NotImplementedException(); - _logger.Value.Debug("Yes!"); + _logger.e_Debug("Yes!"); using OpenFileDialog ofd = new() { @@ -138,7 +150,7 @@ FileInfo cbAskUserForBinary() Filter = $"{SDeleteManager.C_SDBIN_FILE64}|{SDeleteManager.C_SDBIN_FILE64}" }; if (ofd.ShowDialog() != DialogResult.OK) throw new NotImplementedException(); - _logger.Value.Debug($"OpenFileDialog.FileName = '{ofd.FileName}'"); + _logger.e_Debug(ofd.FileName); return new(ofd.FileName); } @@ -149,7 +161,7 @@ FileInfo cbAskUserForBinary() } catch (Exception ex) { - _logger.Value.Error($"_Load", ex); + _logger.e_Error(ex); if (ex is not NotImplementedException)//Not user canceled error ex.e_LogError(true); @@ -170,15 +182,25 @@ FileInfo cbAskUserForBinary() optCleanMode_Clean.Checked = true; + optSource_Files.Checked = true; + optSource_PhyDisk.Checked = true; await FillDisksList(); + var lastRun = uom.AppTools.AppSettings.Get_DateTime("LastRun", DateTime.MinValue); + if (lastRun == DateTime.MinValue) + { + //First RUN + OpenSDeleteHomePage(); + } + uom.AppTools.AppSettings.Save("LastRun", DateTime.Now); + await CheckShellRegistration(true); ProcessCMDLine(); } catch (Exception ex) { - _logger.Value.Error($"_Load2", ex); + _logger.e_Error(ex); llSDeleteBinPath.Text = ex.Message; return; } @@ -188,14 +210,17 @@ FileInfo cbAskUserForBinary() private void _Shown() - => _tbm.Value.SetProgressState(TaskbarProgressBarState.NoProgress); + { + _tbm.Value.SetProgressState(TaskbarProgressBarState.NoProgress); + this.e_StartAutoupdateOnShown("https://raw.githubusercontent.com/uom42/1C_Pasta/master/UpdaterXML.xml"); + } /// Load disk list private async Task FillDisksList() { - _logger.Value.Debug($"FillDisksList"); + _logger.e_Debug($"FillDisksList"); RadioButton? oldSource = _optSources.Where(radio => radio.Checked).FirstOrDefault(); @@ -312,7 +337,7 @@ private void OnSourceChanged() else if (optSource_Files.Checked) _SourceMode = SourceModes.Files; else throw _exSourceError; - _logger.Value.Debug($"OnSourceChanged, _SourceMode = {_SourceMode}"); + _logger.e_Debug($"OnSourceChanged, _SourceMode = {_SourceMode}"); bool isSourceDisk = _SourceMode == SourceModes.PhyDisk || _SourceMode == SourceModes.LogDisk; tlpCleanFreeSpaceMethods.Enabled = isSourceDisk; @@ -327,12 +352,12 @@ private void OnSourceChanged() private async Task OnSource_RefreshLists() { - _logger.Value.Debug("OnSource_RefreshLists"); + _logger.e_Debug(); try { await FillDisksList(); } catch (Exception ex) { - _logger.Value.Error("OnSource_RefreshLists", ex); + _logger.e_Error(ex); ex.e_LogError(true); } finally { UpdateUI(); } @@ -367,7 +392,7 @@ private async Task OnSource_RefreshLists() private void OnSource_DisplaySelectionUI() { - _logger.Value.Debug($"OnSource_DisplaySelectionUI, _SourceMode = {_SourceMode}"); + _logger.e_Debug($"OnSource_DisplaySelectionUI, _SourceMode = {_SourceMode}"); try { @@ -376,17 +401,14 @@ private void OnSource_DisplaySelectionUI() case SourceModes.Dir: { _bffUI.SelectedPath = txtSource_Dir.Text.Trim(); - var dr = _bffUI.ShowDialog(this); - if (dr != DialogResult.OK) return; - + if (_bffUI.ShowDialog(this) != DialogResult.OK) return; txtSource_Dir.Text = _bffUI.SelectedPath; } break; case SourceModes.Files: { - var dr = _ofdUI.ShowDialog(this); - if (dr != DialogResult.OK) return; + if (_ofdUI.ShowDialog(this) != DialogResult.OK) return; FileInfo[] files = _ofdUI .FileNames @@ -402,20 +424,14 @@ private void OnSource_DisplaySelectionUI() throw _exSourceError; } } - catch (Exception ex) - { - ex.e_LogError(true); - } - finally - { - UpdateUI(); - } + catch (Exception ex) { ex.e_LogError(true); } + finally { UpdateUI(); } } /// Update button state by UI selections private void UpdateUI() { - _logger.Value.Debug($"UpdateUI, _SourceMode = {_SourceMode}"); + _logger.e_Debug($"UpdateUI, _SourceMode = {_SourceMode}"); bool bCanRun = false; try @@ -456,36 +472,33 @@ private void UpdateUI() break; } } - catch (Exception ex) - { - _logger.Value.Error($"UpdateUI", ex); - } + catch (Exception ex) { _logger.e_Error(ex); } finally { btnStartStop.Enabled = bCanRun; } } - private DateTime _dtStarted = DateTime.Now; private void OnStartStop() { - _logger.Value.Debug($"OnStartStop, _SourceMode = {_SourceMode}, _isRunning = {_isRunning}"); + _logger.e_Debug($"_SourceMode = {_SourceMode}, _isRunning = {_isRunning}"); if (_isRunning) { tmrElapsed.Stop(); - //tmrElapsed.Enabled = false; - _sdmgr!.Stop(); } else { _dtStarted = DateTime.Now; + _tsElapsed = DateTime.Now - _dtStarted; + _estimatedTimeString = string.Empty; + OnElapsedTimerTick(); tmrElapsed.Start(); _isRunning = true; tlpParams.Enabled = false; lstLog.Items.Clear(); - btnStartStop.Text = "Stop"; + btnStartStop.Text = Localization.Strings.L_STOP; ProgressBarSetState_Marquee(); @@ -533,8 +546,7 @@ private void OnStartStop() } catch (Exception ex) { - _logger.Value.Error($"OnStartStop", ex); - + _logger.e_Error(ex); ProgressBarSetState_Error(); ex.e_LogError(true); OnFinished(); @@ -544,33 +556,47 @@ private void OnStartStop() private void OnFinished() { + _isRunning = false; tmrElapsed.Stop(); - - _logger.Value.Debug("OnFinished"); - + _tsElapsed = DateTime.Now - _dtStarted; + _logger.e_Debug(); SDeleteEngine_DetachEvents(); - _isRunning = false; tlpParams.Enabled = true; btnStartStop.Text = Localization.Strings.L_START; ProgressBarSetState_Finished(); UpdateUI(); + OnElapsedTimerTick(); } - private void OnElapsedTimerTick() - { - TimeSpan tsElapsed = DateTime.Now - _dtStarted; - lblStatus.Text = string.Format(Localization.Strings.L_ELAPSED, tsElapsed.e_ToShellTimeString(8)); - } + + + #region UI Events Helpers + private void OnSDBinary_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { Link ll = e.Link; if (ll.Start == 0) - @"https://docs.microsoft.com/en-us/sysinternals/downloads/sdelete".e_OpenURLInBrowser(); + OpenSDeleteHomePage(); else new Action(() => _sdmgr!.SDeleteBinary.e_OpenExplorer()).e_tryCatch(); } + + + private void OpenSDeleteHomePage() + { + try + { + @"https://docs.microsoft.com/en-us/sysinternals/downloads/sdelete".e_OpenURLInBrowser(); + } + catch (Exception ex) + { + ex.e_LogError(true); + } + } + + #endregion } } diff --git a/SDeleteGUI/frmMain.resx b/SDeleteGUI/frmMain.resx index 466b754..cbe4924 100644 --- a/SDeleteGUI/frmMain.resx +++ b/SDeleteGUI/frmMain.resx @@ -123,6 +123,9 @@ 17, 17 + + 355, 17 + diff --git a/SDeleteGUI/frmMain_CMDLineArgs.cs b/SDeleteGUI/frmMain_CMDLineArgs.cs index 5139542..4155f51 100644 --- a/SDeleteGUI/frmMain_CMDLineArgs.cs +++ b/SDeleteGUI/frmMain_CMDLineArgs.cs @@ -20,15 +20,14 @@ private async Task CheckShellRegistration(bool isFirstRun) _logger.Value.Debug($"CheckShellRegistration()"); llShellRegister.Text = string.Empty; - using Task tskCheckRegistration = new(() => uom.OS.Shell.ContextMenu_IsRegisteredForDirectory(C_SHELL_CONTEXTMENU_MENU_REGVALUE, C_SHELL_CONTEXTMENU_MENU_TITLE, null, C_SHELL_CONTEXTMENU_MENU_ARG_CLEAN_DIR), TaskCreationOptions.LongRunning); - tskCheckRegistration.Start(); - _isShellRegistered = await tskCheckRegistration; + _isShellRegistered = await tskCheckRegistration.e_StartAndWaitAsync(); + llShellRegister.Text = _isShellRegistered ? Localization.Strings.L_SHELL_MENU_UNREGISTER @@ -36,6 +35,10 @@ private async Task CheckShellRegistration(bool isFirstRun) if (!isFirstRun || _isShellRegistered) return; +#if DEBUG + return; +#endif + DialogResult dr = Localization.Strings.Q_REGISTER_SHELL_MENU.e_MsgboxWithCheckboxAsk(C_DIALOGID_DO_NOT_ASK_SHELL_CONTEXT_MENU_REGISTRATION, checkBoxText: Localization.Strings.L_DONT_ASK_AGAIN); _logger.Value.Debug($"MsgboxAskWithCheckbox() = {dr}"); if (dr != DialogResult.Yes) return; diff --git a/SDeleteGUI/frmMain_SDeleteOutput.cs b/SDeleteGUI/frmMain_SDeleteOutput.cs index 96d7b4b..2ec13fc 100644 --- a/SDeleteGUI/frmMain_SDeleteOutput.cs +++ b/SDeleteGUI/frmMain_SDeleteOutput.cs @@ -1,8 +1,6 @@  using SDeleteGUI.Core.SDelete; -using static SDeleteGUI.Core.SDelete.SDeleteManager; - #nullable enable @@ -10,12 +8,23 @@ namespace SDeleteGUI { internal partial class frmMain : Form { + private const int C_MAX_LOG_ROWS = 1000; + + private EventArgs _lastLogRowSync = new(); + private object? _lastLogRow = null; + + private DateTime _dtStarted = DateTime.Now; + private TimeSpan? _tsElapsed; + private string _estimatedTimeString = string.Empty; + private void SDeleteEngine_AttachEvents() { _sdmgr!.OutputRAW += OnCore_Data_RAW; _sdmgr!.Error += OnCore_Error; _sdmgr!.Finished += OnFinished; + + _lastLogRow = null; } private void SDeleteEngine_DetachEvents() @@ -31,10 +40,6 @@ private void SDeleteEngine_DetachEvents() private void OnCore_Error(object _, DataReceivedEventArgs e) => LogAddErrorMTSafe(e); - //private void OnCore_Data_Progress(object _, ProgressInfoEventArgs e) => this.e_runInUIThread(() => ProgressBarSetState_Progress(e.ProgressPercent)); - - - private const int C_MAX_LOG_ROWS = 1000; private void LogAddErrorMTSafe(DataReceivedEventArgs? e) { @@ -56,9 +61,12 @@ void addRowInUIThread() lstLog.e_runOnLockedUpdateMTSafe(addRowInUIThread); } + + + private void LogAddRowMTSafe(DataReceivedEventArgsEx? e) { - string? s = e?.Data; + string? s = e?.RAWData; if (string.IsNullOrWhiteSpace(s)) return;//Skip empty lines Debug.WriteLine($"Output Data: '{s}'"); @@ -67,49 +75,147 @@ void addRowInUIThread() { try { - object? lastRow = lstLog.Items.Cast().LastOrDefault(); - if (lastRow != null) + lock (_lastLogRowSync) { - //We will search for string equality with previous log line //and if we found - we just replace text in last report line - const int MIN_EQUAL_CHARS = 3; - const int MIN_EQUAL_WORDS = 2; - - switch (lastRow) + if (_lastLogRow != null) { - case DataReceivedEventArgsEx dreax: - { - //Previous Row is DataReceivedEventArgsEx! - var eq = s!.e_GetEqualityMetrics(dreax.Data); - - if ((eq.CommonPrefix == s) - || (eq.CommonPrefix.Length >= MIN_EQUAL_CHARS && eq.UniqueWordsInBothStrings.Length >= MIN_EQUAL_WORDS)) + switch (_lastLogRow) + { + case DataReceivedEventArgsEx dreaxlastLogRow: { - //Looks like the some string as previous with some changes... Just update last row - - e!.UpdateTimestamp(dreax.Timestamp); - lstLog.Items[lstLog.Items.Count - 1] = e; - return; + //Previous Row is DataReceivedEventArgsEx + bool rowLooksLikePrevious = false; + if (chkCompactOutput.Checked) + { + if (e!.GetType().FullName != dreaxlastLogRow.GetType().FullName) + { + rowLooksLikePrevious = false; + } + else if (e!.GetType().Namespace == typeof(SDeleteGUI.Core.SDelete.OutputLocalization.Progress_BaseEventArgs).Namespace) + { + rowLooksLikePrevious = true; + } + + /* + const string C_OUTPUT_DELETED = ".deleted."; + //We will search for string equality with previous log line //and if we found - we just replace text in last report line + const int MIN_EQUAL_CHARS = 3; + const int MIN_EQUAL_WORDS = 2; + + else if ((_SourceMode is SourceModes.Dir or SourceModes.Files) + && s!.EndsWith(C_OUTPUT_DELETED, StringComparison.InvariantCultureIgnoreCase) && dreaxlastLogRow.RAWData.EndsWith(C_OUTPUT_DELETED, StringComparison.InvariantCultureIgnoreCase)) + { + //Both current and previous rows EndsWith("deleted.") + rowLooksLikePrevious = true; + } + else + { + //var eq = s!.e_GetEqualityMetrics(dreaxlastLogRow.RAWData); + //rowLooksLikePrevious = ((eq.CommonPrefix == s) || (eq.CommonPrefix.Length >= MIN_EQUAL_CHARS && eq.UniqueWordsInBothStrings.Length >= MIN_EQUAL_WORDS)); + } + */ + } + + if (rowLooksLikePrevious) + { + //Looks like the some string as previous with some changes... Just update last row + e!.UpdateTimestamp(dreaxlastLogRow.Timestamp); + lstLog.e_SetLastItem(e); + _lastLogRow = e; + return; + } + break; } - break; - } + } } - } - //No found equality. Just add new row to log + //Add new row to log lstLog.Items.Add(e!); - if (lstLog.Items.Count > 1) lstLog.SelectedIndex = (lstLog.Items.Count - 1); + _lastLogRow = e!; + lstLog.e_SelectLastRow(); } finally { lstLog.e_LimitRowsCountTo(C_MAX_LOG_ROWS); - if (e!.ProgressInfo != null) ProgressBarSetState_Progress(e.ProgressInfo.ProgressPercent); + + _estimatedTimeString = string.Empty; + float totalProgress = -1f; + + switch (e) + { + case SDeleteGUI.Core.SDelete.OutputLocalization.Progress_PhyDisk_ProgressEventArgs pdp: + { + totalProgress = pdp.TotalPercent; + + if (totalProgress > 0 && _sdmgr!.Passes > 1 && pdp.PassNumber > 0) + { + //Recalculation total progress over all stages + float maxPercent = 100f * (float)_sdmgr!.Passes; + float currentPercent = ((pdp.PassNumber - 1) * 100f) + totalProgress; + totalProgress = (currentPercent / maxPercent) * 100f; + } + + _estimatedTimeString = $". Всего выполнено: {totalProgress:N2}%"; + + //Recalculating Estimation + const double ESTIMATION_MIN_SECONDS_SPENT = 10d; + const double ESTIMATION_MIN_PERCENT = .1d; + + double timeSpent = (DateTime.Now - _dtStarted).TotalSeconds; + if (timeSpent >= ESTIMATION_MIN_SECONDS_SPENT && totalProgress >= ESTIMATION_MIN_PERCENT) + { + //double progressPercent = totalProgress; + double progressPercentPerSecond = (totalProgress) / timeSpent; + double progressPercentLeave = (100d - totalProgress); + double dblSecondsLeave = (progressPercentLeave / progressPercentPerSecond).e_Round(0); + if (dblSecondsLeave >= 1d) + { + dblSecondsLeave *= 1000d; + + if (dblSecondsLeave <= (double)UInt32.MaxValue) + { + int iSecondsLeave = (int)dblSecondsLeave; + string sSecondsLeave = uom.WinAPI.Shell.StrFromTimeInterval(iSecondsLeave); + _estimatedTimeString += $". {Localization.Strings.M_ESTIMATED}: {sSecondsLeave}"; + } + } + } + + break; + } + case SDeleteGUI.Core.SDelete.OutputLocalization.Progress_BaseEventArgs pb: + { + totalProgress = pb.CurrentOperationProgressPercent; + break; + } + } + + if (totalProgress >= 0) ProgressBarSetState_Progress(totalProgress); } } - //this.e_runInUIThread(addRowInUIThread); lstLog.e_runOnLockedUpdateMTSafe(addRowInUIThread); } + + + private void OnElapsedTimerTick() + { + string s; + if (_isRunning) + { + _tsElapsed = DateTime.Now - _dtStarted; + s = string.Format(Localization.Strings.M_ELAPSED, _tsElapsed.Value.e_ToShellTimeString(8)) + + _estimatedTimeString; + } + else + { + s = !_tsElapsed.HasValue + ? "" + : string.Format(Localization.Strings.M_COMPLETED_AT, _tsElapsed.Value.e_ToShellTimeString(8)); + } + lblStatus.Text = s; + } } } diff --git a/UpdaterXML.xml b/UpdaterXML.xml new file mode 100644 index 0000000..4d268d0 --- /dev/null +++ b/UpdaterXML.xml @@ -0,0 +1,6 @@ + + + 1.23.12.4 + https://github.com/uom42/1C_Pasta/releases/download/v1.0.0.2/Release_1_0_0_2.zip + false +