diff --git a/.gitignore b/.gitignore index 23817a74..905236c7 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ bld/ # Visual Studio 2015 cache/options directory .vs/ +.vscode/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ diff --git a/installer/BcuSetup.iss b/installer/BcuSetup.iss index d4374a16..cd9b07c1 100644 --- a/installer/BcuSetup.iss +++ b/installer/BcuSetup.iss @@ -140,6 +140,7 @@ Type: files; Name: "{app}\CleanLogs.bat" Type: files; Name: "{app}\BCUninstaller.settings" Type: files; Name: "{app}\*.log" Type: files; Name: "{app}\Exception_*.zip" +Type: files; Name: "{app}\CustomNotes.xml" Type: files; Name: "{app}\InfoCache.xml" Type: files; Name: "{app}\CertCache.xml" Type: files; Name: "{app}\UsageStatistics.xml" @@ -148,6 +149,7 @@ Type: files; Name: "{app}\*\CleanLogs.bat" Type: files; Name: "{app}\*\BCUninstaller.settings" Type: files; Name: "{app}\*\*.log" Type: files; Name: "{app}\*\Exception_*.zip" +Type: files; Name: "{app}\*\CustomNotes.xml" Type: files; Name: "{app}\*\InfoCache.xml" Type: files; Name: "{app}\*\CertCache.xml" Type: files; Name: "{app}\*\UsageStatistics.xml" diff --git a/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.Designer.cs b/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.Designer.cs new file mode 100644 index 00000000..88077545 --- /dev/null +++ b/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.Designer.cs @@ -0,0 +1,90 @@ +namespace BulkCrapUninstaller.Forms +{ + partial class CustomNoteDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CustomNoteDialog)); + this.txtNote = new System.Windows.Forms.TextBox(); + this.btnOk = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.SuspendLayout(); + + // txtNote + this.txtNote.AcceptsReturn = true; + this.txtNote.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.txtNote.Location = new System.Drawing.Point(12, 12); + this.txtNote.Multiline = true; + this.txtNote.Name = "txtNote"; + this.txtNote.Size = new System.Drawing.Size(360, 150); + this.txtNote.TabIndex = 0; + + // btnOk + this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnOk.Location = new System.Drawing.Point(216, 175); + this.btnOk.Name = "btnOk"; + this.btnOk.Size = new System.Drawing.Size(75, 23); + this.btnOk.TabIndex = 1; + resources.ApplyResources(this.btnOk, "btnOk"); + this.btnOk.UseVisualStyleBackColor = true; + + // btnCancel + this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(297, 175); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 2; + resources.ApplyResources(this.btnCancel, "btnCancel"); + this.btnCancel.UseVisualStyleBackColor = true; + + // CustomNoteDialog + this.AcceptButton = this.btnOk; + this.CancelButton = this.btnCancel; + this.ClientSize = new System.Drawing.Size(384, 211); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.btnOk); + this.Controls.Add(this.txtNote); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; + this.Name = "CustomNoteDialog"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + resources.ApplyResources(this, "$this"); + this.ResumeLayout(false); + this.PerformLayout(); + } + + #endregion + + private System.Windows.Forms.TextBox txtNote; + private System.Windows.Forms.Button btnOk; + private System.Windows.Forms.Button btnCancel; + } +} diff --git a/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.cs b/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.cs new file mode 100644 index 00000000..172253c3 --- /dev/null +++ b/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.cs @@ -0,0 +1,26 @@ +using System.Windows.Forms; + +namespace BulkCrapUninstaller.Forms +{ + public partial class CustomNoteDialog : Form + { + public string NoteText + { + get => txtNote.Text; + set => txtNote.Text = value; + } + + public CustomNoteDialog(string appName, string existingNote) : this() + { + // Append the app name to the localized base title + this.Text = this.Text + appName; + this.NoteText = existingNote; + this.StartPosition = FormStartPosition.CenterParent; + } + + private CustomNoteDialog() + { + InitializeComponent(); + } + } +} diff --git a/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.resx b/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.resx new file mode 100644 index 00000000..e2121984 --- /dev/null +++ b/source/BulkCrapUninstaller/Forms/Helpers/CustomNoteDialog.resx @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + OK + + + Cancel + + + Custom Note for + + \ No newline at end of file diff --git a/source/BulkCrapUninstaller/Forms/Windows/MainWindow.Designer.cs b/source/BulkCrapUninstaller/Forms/Windows/MainWindow.Designer.cs index e5303b8a..35b2b23c 100644 --- a/source/BulkCrapUninstaller/Forms/Windows/MainWindow.Designer.cs +++ b/source/BulkCrapUninstaller/Forms/Windows/MainWindow.Designer.cs @@ -1,4 +1,4 @@ -using System.ComponentModel; +using System.ComponentModel; using System.Windows.Forms; using BrightIdeasSoftware; using BulkCrapUninstaller.Controls; @@ -48,6 +48,7 @@ private void InitializeComponent() olvColumnRegistryKeyName = new OLVColumn(); olvColumnGuid = new OLVColumn(); olvColumnQuietUninstallString = new OLVColumn(); + olvColumnCustomNote = new OLVColumn(); treeMap1 = new SimpleTreeMap.TreeMap(); toolStrip = new ToolStrip(); toolStripButton1 = new ToolStripButton(); @@ -149,12 +150,12 @@ private void InitializeComponent() automaticallyStartedToolStripMenuItem = new ToolStripMenuItem(); onlyWebBrowsersToolStripMenuItem = new ToolStripMenuItem(); toolStripSeparator31 = new ToolStripSeparator(); - viewTweaksToolStripMenuItem = new ToolStripMenuItem(); - viewUnregisteredToolStripMenuItem = new ToolStripMenuItem(); - viewUpdatesToolStripMenuItem = new ToolStripMenuItem(); - viewInvalidToolStripMenuItem = new ToolStripMenuItem(); - viewWindowsFeaturesToolStripMenuItem = new ToolStripMenuItem(); - viewWindowsStoreAppsToolStripMenuItem = new ToolStripMenuItem(); + viewTweaksToolStripMenuItem = new ToolStripMenuItem(); + viewUnregisteredToolStripMenuItem = new ToolStripMenuItem(); + viewUpdatesToolStripMenuItem = new ToolStripMenuItem(); + viewInvalidToolStripMenuItem = new ToolStripMenuItem(); + viewWindowsFeaturesToolStripMenuItem = new ToolStripMenuItem(); + viewWindowsStoreAppsToolStripMenuItem = new ToolStripMenuItem(); toolStripSeparator28 = new ToolStripSeparator(); searchToolStripMenuItem = new ToolStripMenuItem(); basicOperationsToolStripMenuItem = new ToolStripMenuItem(); @@ -234,6 +235,7 @@ private void InitializeComponent() globalHotkeys1 = new Klocman.Subsystems.GlobalHotkeys(); splashScreen1 = new Klocman.Forms.SplashScreen(); usageTracker = new UsageTracker(); + editCustomNoteMenuItem = new ToolStripMenuItem(); ((ISupportInitialize)splitContainer1).BeginInit(); splitContainer1.Panel1.SuspendLayout(); splitContainer1.Panel2.SuspendLayout(); @@ -298,6 +300,7 @@ private void InitializeComponent() // uninstallerObjectListView // uninstallerObjectListView.AllColumns.Add(olvColumnDisplayName); + uninstallerObjectListView.AllColumns.Add(olvColumnCustomNote); uninstallerObjectListView.AllColumns.Add(olvColumnPublisher); uninstallerObjectListView.AllColumns.Add(olvColumnCertificate); uninstallerObjectListView.AllColumns.Add(olvColumnRating); @@ -322,7 +325,7 @@ private void InitializeComponent() uninstallerObjectListView.CellEditActivation = ObjectListView.CellEditActivateMode.DoubleClick; uninstallerObjectListView.CellEditUseWholeCell = false; uninstallerObjectListView.CheckBoxes = true; - uninstallerObjectListView.Columns.AddRange(new ColumnHeader[] { olvColumnDisplayName, olvColumnPublisher, olvColumnCertificate, olvColumnRating, olvColumnDisplayVersion, olvColumnInstallDate, olvColumnSize, olvColumnStartup, olvColumnIs64, olvColumnUninstallString, olvColumnAbout, olvColumnInstallSource, olvColumnInstallLocation, olvColumnUninstallerKind, olvColumnSystemComponent, olvColumnProtected, olvColumnIntegrity, olvColumnRegistryKeyName, olvColumnGuid, olvColumnQuietUninstallString }); + uninstallerObjectListView.Columns.AddRange(new ColumnHeader[] { olvColumnDisplayName, olvColumnCustomNote, olvColumnPublisher, olvColumnCertificate, olvColumnRating, olvColumnDisplayVersion, olvColumnInstallDate, olvColumnSize, olvColumnStartup, olvColumnIs64, olvColumnUninstallString, olvColumnAbout, olvColumnInstallSource, olvColumnInstallLocation, olvColumnUninstallerKind, olvColumnSystemComponent, olvColumnProtected, olvColumnIntegrity, olvColumnRegistryKeyName, olvColumnGuid, olvColumnQuietUninstallString }); resources.ApplyResources(uninstallerObjectListView, "uninstallerObjectListView"); uninstallerObjectListView.FullRowSelect = true; uninstallerObjectListView.GridLines = true; @@ -438,6 +441,12 @@ private void InitializeComponent() // resources.ApplyResources(olvColumnQuietUninstallString, "olvColumnQuietUninstallString"); // + // olvColumnCustomNote + // + olvColumnCustomNote.AspectName = "CustomNote"; + olvColumnCustomNote.Text = "Custom Note"; + olvColumnCustomNote.Width = 150; + // // treeMap1 // resources.ApplyResources(treeMap1, "treeMap1"); @@ -629,7 +638,7 @@ private void InitializeComponent() // uninstallListContextMenuStrip // uninstallListContextMenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20); - uninstallListContextMenuStrip.Items.AddRange(new ToolStripItem[] { uninstallContextMenuStripItem, quietUninstallContextMenuStripItem, manualUninstallToolStripMenuItem1, uninstallUsingMsiExecContextMenuStripItem, toolStripSeparator3, excludeToolStripMenuItem, includeToolStripMenuItem, toolStripSeparatorFiltering, runToolStripMenuItem, toolStripSeparator8, copyToClipboardContextMenuStripItem, deleteRegistryEntryContextMenuStripItem, renameContextMenuStripItem, toolStripSeparator6, openInExplorerContextMenuStripItem, openWebPageContextMenuStripItem, lookUpOnlineToolStripMenuItem, rateToolStripMenuItem, toolStripSeparator7, propertiesContextMenuStripItem }); + uninstallListContextMenuStrip.Items.AddRange(new ToolStripItem[] { uninstallContextMenuStripItem, quietUninstallContextMenuStripItem, manualUninstallToolStripMenuItem1, uninstallUsingMsiExecContextMenuStripItem, toolStripSeparator3, excludeToolStripMenuItem, includeToolStripMenuItem, toolStripSeparatorFiltering, runToolStripMenuItem, toolStripSeparator8, copyToClipboardContextMenuStripItem, deleteRegistryEntryContextMenuStripItem, renameContextMenuStripItem, toolStripSeparator6, openInExplorerContextMenuStripItem, openWebPageContextMenuStripItem, lookUpOnlineToolStripMenuItem, rateToolStripMenuItem, toolStripSeparator7, editCustomNoteMenuItem, propertiesContextMenuStripItem }); uninstallListContextMenuStrip.Name = "uninstallListContextMenuStrip"; resources.ApplyResources(uninstallListContextMenuStrip, "uninstallListContextMenuStrip"); uninstallListContextMenuStrip.Opening += UpdateUninstallListContextMenuStrip; @@ -768,6 +777,12 @@ private void InitializeComponent() resources.ApplyResources(renameContextMenuStripItem, "renameContextMenuStripItem"); renameContextMenuStripItem.Click += RenameEntries; // + // editCustomNoteMenuItem + // + editCustomNoteMenuItem.Name = "editCustomNoteMenuItem"; + editCustomNoteMenuItem.Text = "Edit note..."; + editCustomNoteMenuItem.Click += editCustomNoteMenuItem_Click; + // // toolStripSeparator6 // toolStripSeparator6.Name = "toolStripSeparator6"; @@ -1011,7 +1026,7 @@ private void InitializeComponent() // // filteringToolStripMenuItem // - filteringToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { advancedApplicationsToolStripMenuItem, basicApplicationsToolStripMenuItem, systemComponentsToolStripMenuItem, everythingToolStripMenuItem, toolStripSeparator20, automaticallyStartedToolStripMenuItem, onlyWebBrowsersToolStripMenuItem, toolStripSeparator31, viewTweaksToolStripMenuItem, viewUnregisteredToolStripMenuItem, viewUpdatesToolStripMenuItem, viewInvalidToolStripMenuItem, viewWindowsFeaturesToolStripMenuItem, viewWindowsStoreAppsToolStripMenuItem, toolStripSeparator28, searchToolStripMenuItem }); + filteringToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { advancedApplicationsToolStripMenuItem, basicApplicationsToolStripMenuItem, systemComponentsToolStripMenuItem, everythingToolStripMenuItem, toolStripSeparator20, automaticallyStartedToolStripMenuItem, onlyWebBrowsersToolStripMenuItem, toolStripSeparator31, viewTweaksToolStripMenuItem, viewUnregisteredToolStripMenuItem, viewUpdatesToolStripMenuItem, viewInvalidToolStripMenuItem, viewWindowsFeaturesToolStripMenuItem, viewWindowsStoreAppsToolStripMenuItem, toolStripSeparator28, searchToolStripMenuItem }); filteringToolStripMenuItem.Name = "filteringToolStripMenuItem"; resources.ApplyResources(filteringToolStripMenuItem, "filteringToolStripMenuItem"); filteringToolStripMenuItem.DropDownOpening += filteringToolStripMenuItem_DropDownOpening; @@ -1075,22 +1090,22 @@ private void InitializeComponent() viewUnregisteredToolStripMenuItem.Name = "viewUnregisteredToolStripMenuItem"; resources.ApplyResources(viewUnregisteredToolStripMenuItem, "viewUnregisteredToolStripMenuItem"); viewUnregisteredToolStripMenuItem.Click += viewUnregisteredToolStripMenuItem_Click; - // - // viewUpdatesToolStripMenuItem - // - viewUpdatesToolStripMenuItem.Name = "viewUpdatesToolStripMenuItem"; - resources.ApplyResources(viewUpdatesToolStripMenuItem, "viewUpdatesToolStripMenuItem"); - viewUpdatesToolStripMenuItem.Click += viewUpdatesToolStripMenuItem_Click; - // - // viewInvalidToolStripMenuItem - // - viewInvalidToolStripMenuItem.Name = "viewInvalidToolStripMenuItem"; - resources.ApplyResources(viewInvalidToolStripMenuItem, "viewInvalidToolStripMenuItem"); - viewInvalidToolStripMenuItem.Click += viewInvalidToolStripMenuItem_Click; - // - // viewWindowsFeaturesToolStripMenuItem - // - viewWindowsFeaturesToolStripMenuItem.Name = "viewWindowsFeaturesToolStripMenuItem"; + // + // viewUpdatesToolStripMenuItem + // + viewUpdatesToolStripMenuItem.Name = "viewUpdatesToolStripMenuItem"; + resources.ApplyResources(viewUpdatesToolStripMenuItem, "viewUpdatesToolStripMenuItem"); + viewUpdatesToolStripMenuItem.Click += viewUpdatesToolStripMenuItem_Click; + // + // viewInvalidToolStripMenuItem + // + viewInvalidToolStripMenuItem.Name = "viewInvalidToolStripMenuItem"; + resources.ApplyResources(viewInvalidToolStripMenuItem, "viewInvalidToolStripMenuItem"); + viewInvalidToolStripMenuItem.Click += viewInvalidToolStripMenuItem_Click; + // + // viewWindowsFeaturesToolStripMenuItem + // + viewWindowsFeaturesToolStripMenuItem.Name = "viewWindowsFeaturesToolStripMenuItem"; resources.ApplyResources(viewWindowsFeaturesToolStripMenuItem, "viewWindowsFeaturesToolStripMenuItem"); viewWindowsFeaturesToolStripMenuItem.Click += viewWindowsFeaturesToolStripMenuItem_Click; // @@ -1618,15 +1633,16 @@ private void InitializeComponent() internal OLVColumn olvColumnGuid; internal OLVColumn olvColumnSize; internal OLVColumn olvColumnInstallSource; - internal OLVColumn olvColumnInstallLocation; - internal OLVColumn olvColumnUninstallerKind; - internal OLVColumn olvColumnAbout; - internal OLVColumn olvColumnRegistryKeyName; - internal OLVColumn olvColumnCertificate; - internal OLVColumn olvColumnSystemComponent; - internal OLVColumn olvColumnIntegrity; - internal OLVColumn olvColumnQuietUninstallString; - internal OLVColumn olvColumnProtected; + internal OLVColumn olvColumnInstallLocation; + internal OLVColumn olvColumnUninstallerKind; + internal OLVColumn olvColumnAbout; + internal OLVColumn olvColumnRegistryKeyName; + internal OLVColumn olvColumnCertificate; + internal OLVColumn olvColumnSystemComponent; + internal OLVColumn olvColumnIntegrity; + internal OLVColumn olvColumnQuietUninstallString; + internal OLVColumn olvColumnProtected; + internal OLVColumn olvColumnCustomNote; private SaveFileDialog exportDialog; private ContextMenuStrip uninstallListContextMenuStrip; private ToolStripMenuItem uninstallContextMenuStripItem; @@ -1767,13 +1783,13 @@ private void InitializeComponent() private ToolStripMenuItem alternativeToToolStripMenuItem; private ToolStripMenuItem toolStripMenuItem15; private ToolStripMenuItem toolStripMenuItem16; - private ToolStripMenuItem openSystemRestoreToolStripMenuItem; - private Klocman.Forms.SplashScreen splashScreen1; - private ToolStripSeparator toolStripSeparator3; - private ToolStripMenuItem runToolStripMenuItem; - private ToolStripMenuItem viewUpdatesToolStripMenuItem; - private ToolStripMenuItem viewInvalidToolStripMenuItem; - private ToolStripMenuItem targetMenuItem; + private ToolStripMenuItem openSystemRestoreToolStripMenuItem; + private Klocman.Forms.SplashScreen splashScreen1; + private ToolStripSeparator toolStripSeparator3; + private ToolStripMenuItem runToolStripMenuItem; + private ToolStripMenuItem viewUpdatesToolStripMenuItem; + private ToolStripMenuItem viewInvalidToolStripMenuItem; + private ToolStripMenuItem targetMenuItem; private ToolStripSeparator toolStripSeparator25; private ToolStripSeparator toolStripSeparator26; private ToolStripMenuItem fossHubcomToolStripMenuItem; @@ -1818,6 +1834,6 @@ private void InitializeComponent() private ToolStripMenuItem createRestorePointToolStripMenuItem; private ToolStripSeparator toolStripSeparator33; private ToolStripMenuItem autosizeAllColumnsToolStripMenuItem; + private ToolStripMenuItem editCustomNoteMenuItem; } } - diff --git a/source/BulkCrapUninstaller/Forms/Windows/MainWindow.cs b/source/BulkCrapUninstaller/Forms/Windows/MainWindow.cs index 3d80d2e0..c85c0c60 100644 --- a/source/BulkCrapUninstaller/Forms/Windows/MainWindow.cs +++ b/source/BulkCrapUninstaller/Forms/Windows/MainWindow.cs @@ -1904,5 +1904,42 @@ private void autosizeAllColumnsToolStripMenuItem_Click(object sender, EventArgs { uninstallerObjectListView.AutoResizeColumns(); } + + private void editCustomNoteMenuItem_Click(object sender, EventArgs e) + { + var selectedUninstallers = _listView.SelectedUninstallers.ToList(); + if (selectedUninstallers.Count == 0) return; + + string title; + string existingNote = string.Empty; + + if (selectedUninstallers.Count == 1) + { + var entry = selectedUninstallers[0]; + title = entry.DisplayName; + existingNote = entry.CustomNote; + } + else + { + title = $"{selectedUninstallers.Count} items"; + var firstNote = selectedUninstallers[0].CustomNote ?? string.Empty; + if (selectedUninstallers.All(x => (x.CustomNote ?? string.Empty) == firstNote)) + { + existingNote = firstNote; + } + } + + using (var dialog = new BulkCrapUninstaller.Forms.CustomNoteDialog(title, existingNote)) + { + if (dialog.ShowDialog(this) == DialogResult.OK) + { + foreach (var entry in selectedUninstallers) + { + entry.CustomNote = dialog.NoteText; + } + this.uninstallerObjectListView.RefreshObjects(selectedUninstallers); + } + } + } } } diff --git a/source/UninstallTools/ApplicationUninstallerEntry.cs b/source/UninstallTools/ApplicationUninstallerEntry.cs index b5130184..4e1fb43a 100644 --- a/source/UninstallTools/ApplicationUninstallerEntry.cs +++ b/source/UninstallTools/ApplicationUninstallerEntry.cs @@ -117,6 +117,14 @@ public string DisplayName [LocalisedName(typeof(Localisation), nameof(Localisation.Comment))] public string Comment { get; set; } + [XmlIgnore] + [LocalisedName(typeof(Localisation), nameof(Localisation.CustomNote))] + public string CustomNote + { + get => CustomNotesManager.GetNote(GetCacheId()); + set => CustomNotesManager.SetNote(GetCacheId(), value); + } + [LocalisedName(typeof(Localisation), nameof(Localisation.DisplayIcon))] public string DisplayIcon { @@ -177,20 +185,20 @@ public string InstallSource /// /// True if this is an update for another product /// - [ComparisonTarget] - [LocalisedName(typeof(Localisation), nameof(Localisation.IsUpdate))] - public bool IsUpdate { get; set; } - - [XmlIgnore] - [ComparisonTarget] - public bool IsScriptTweak => !string.IsNullOrEmpty(RatingId) && - RatingId.StartsWith("Tweak-", StringComparison.OrdinalIgnoreCase); - - /// - /// True if the application can be uninstalled. False if the uninstaller is missing or is otherwise invalid. - /// - [ComparisonTarget] - [LocalisedName(typeof(Localisation), nameof(Localisation.IsValid))] + [ComparisonTarget] + [LocalisedName(typeof(Localisation), nameof(Localisation.IsUpdate))] + public bool IsUpdate { get; set; } + + [XmlIgnore] + [ComparisonTarget] + public bool IsScriptTweak => !string.IsNullOrEmpty(RatingId) && + RatingId.StartsWith("Tweak-", StringComparison.OrdinalIgnoreCase); + + /// + /// True if the application can be uninstalled. False if the uninstaller is missing or is otherwise invalid. + /// + [ComparisonTarget] + [LocalisedName(typeof(Localisation), nameof(Localisation.IsValid))] public bool IsValid { get; set; } /// @@ -528,4 +536,4 @@ private static string CleanupPath(string path, bool isFilename = false) return path.TrimEnd('\\'); } } -} +} diff --git a/source/UninstallTools/CustomNotesManager.cs b/source/UninstallTools/CustomNotesManager.cs new file mode 100644 index 00000000..5193185a --- /dev/null +++ b/source/UninstallTools/CustomNotesManager.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Klocman.Tools; + +namespace UninstallTools +{ + public static class CustomNotesManager + { + private static readonly string NotesFilePath = Path.Combine(UninstallToolsGlobalConfig.AssemblyLocation, "CustomNotes.xml"); + private static Dictionary _notesCache = new Dictionary(); + + static CustomNotesManager() + { + if (File.Exists(NotesFilePath)) + { + try + { + var loaded = SerializationTools.DeserializeFromXml>(NotesFilePath); + if (loaded != null) + { + _notesCache = loaded + .Where(x => !string.IsNullOrEmpty(x.CacheId) && !string.IsNullOrEmpty(x.Note)) + .ToDictionary(x => x.CacheId, x => x.Note); + } + } + catch (Exception ex) + { + Console.WriteLine("Failed to load CustomNotes.xml: " + ex.Message); + } + } + } + + public static string GetNote(string cacheId) + { + if (string.IsNullOrEmpty(cacheId)) return string.Empty; + return _notesCache.TryGetValue(cacheId, out var note) ? note : string.Empty; + } + + public static void SetNote(string cacheId, string note) + { + if (string.IsNullOrEmpty(cacheId)) return; + + if (string.IsNullOrEmpty(note)) + _notesCache.Remove(cacheId); + else + _notesCache[cacheId] = note; + + Save(); + } + + private static void Save() + { + try + { + var listToSave = _notesCache.Select(kv => new NoteEntry { CacheId = kv.Key, Note = kv.Value }).ToList(); + SerializationTools.SerializeToXml(NotesFilePath, listToSave); + } + catch (Exception ex) + { + Console.WriteLine("Failed to save CustomNotes.xml: " + ex.Message); + } + } + + public class NoteEntry + { + public string CacheId { get; set; } + public string Note { get; set; } + } + } +} diff --git a/source/UninstallTools/Properties/Localisation.Designer.cs b/source/UninstallTools/Properties/Localisation.Designer.cs index bc0cc369..eee9b68e 100644 --- a/source/UninstallTools/Properties/Localisation.Designer.cs +++ b/source/UninstallTools/Properties/Localisation.Designer.cs @@ -1445,5 +1445,14 @@ internal static string UninstallString { return ResourceManager.GetString("UninstallString", resourceCulture); } } + + /// + /// Looks up a localized string similar to Custom Note. + /// + internal static string CustomNote { + get { + return ResourceManager.GetString("CustomNote", resourceCulture); + } + } } } diff --git a/source/UninstallTools/Properties/Localisation.resx b/source/UninstallTools/Properties/Localisation.resx index b00681ec..602955da 100644 --- a/source/UninstallTools/Properties/Localisation.resx +++ b/source/UninstallTools/Properties/Localisation.resx @@ -587,4 +587,7 @@ Located directly inside a Known Folder + + Custom Note + \ No newline at end of file