diff --git a/source/BulkCrapUninstaller/BulkCrapUninstaller.csproj b/source/BulkCrapUninstaller/BulkCrapUninstaller.csproj index ecc183a7..1a3167ce 100644 --- a/source/BulkCrapUninstaller/BulkCrapUninstaller.csproj +++ b/source/BulkCrapUninstaller/BulkCrapUninstaller.csproj @@ -47,19 +47,23 @@ - - - - + + + + - - - - - - + + + + + + + + + + @@ -84,4 +88,4 @@ Resources.Designer.cs - \ 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 ac46bb91..4302d6b8 100644 --- a/source/BulkCrapUninstaller/Forms/Windows/MainWindow.Designer.cs +++ b/source/BulkCrapUninstaller/Forms/Windows/MainWindow.Designer.cs @@ -39,12 +39,13 @@ private void InitializeComponent() olvColumnUninstallString = new OLVColumn(); olvColumnAbout = new OLVColumn(); olvColumnInstallSource = new OLVColumn(); - olvColumnInstallLocation = new OLVColumn(); - olvColumnUninstallerKind = new OLVColumn(); - olvColumnSystemComponent = new OLVColumn(); - olvColumnProtected = new OLVColumn(); - olvColumnRegistryKeyName = new OLVColumn(); - olvColumnGuid = new OLVColumn(); + olvColumnInstallLocation = new OLVColumn(); + olvColumnUninstallerKind = new OLVColumn(); + olvColumnSystemComponent = new OLVColumn(); + olvColumnStatus = new OLVColumn(); + olvColumnProtected = new OLVColumn(); + olvColumnRegistryKeyName = new OLVColumn(); + olvColumnGuid = new OLVColumn(); olvColumnQuietUninstallString = new OLVColumn(); treeMap1 = new SimpleTreeMap.TreeMap(); toolStrip = new ToolStrip(); @@ -305,21 +306,22 @@ private void InitializeComponent() uninstallerObjectListView.AllColumns.Add(olvColumnUninstallString); uninstallerObjectListView.AllColumns.Add(olvColumnAbout); uninstallerObjectListView.AllColumns.Add(olvColumnInstallSource); - uninstallerObjectListView.AllColumns.Add(olvColumnInstallLocation); - uninstallerObjectListView.AllColumns.Add(olvColumnUninstallerKind); - uninstallerObjectListView.AllColumns.Add(olvColumnSystemComponent); - uninstallerObjectListView.AllColumns.Add(olvColumnProtected); - uninstallerObjectListView.AllColumns.Add(olvColumnRegistryKeyName); - uninstallerObjectListView.AllColumns.Add(olvColumnGuid); + uninstallerObjectListView.AllColumns.Add(olvColumnInstallLocation); + uninstallerObjectListView.AllColumns.Add(olvColumnUninstallerKind); + uninstallerObjectListView.AllColumns.Add(olvColumnSystemComponent); + uninstallerObjectListView.AllColumns.Add(olvColumnStatus); + uninstallerObjectListView.AllColumns.Add(olvColumnProtected); + uninstallerObjectListView.AllColumns.Add(olvColumnRegistryKeyName); + uninstallerObjectListView.AllColumns.Add(olvColumnGuid); uninstallerObjectListView.AllColumns.Add(olvColumnQuietUninstallString); uninstallerObjectListView.AllowColumnReorder = true; - uninstallerObjectListView.BorderStyle = BorderStyle.None; - uninstallerObjectListView.CellEditActivation = ObjectListView.CellEditActivateMode.DoubleClick; - uninstallerObjectListView.CellEditUseWholeCell = false; - uninstallerObjectListView.CheckBoxes = true; - uninstallerObjectListView.Columns.AddRange(new ColumnHeader[] { olvColumnDisplayName, olvColumnPublisher, olvColumnRating, olvColumnDisplayVersion, olvColumnInstallDate, olvColumnSize, olvColumnStartup, olvColumnIs64, olvColumnUninstallString, olvColumnAbout, olvColumnInstallSource, olvColumnInstallLocation, olvColumnUninstallerKind, olvColumnSystemComponent, olvColumnProtected, olvColumnRegistryKeyName, olvColumnGuid, olvColumnQuietUninstallString }); - resources.ApplyResources(uninstallerObjectListView, "uninstallerObjectListView"); - uninstallerObjectListView.FullRowSelect = true; + uninstallerObjectListView.BorderStyle = BorderStyle.None; + uninstallerObjectListView.CellEditActivation = ObjectListView.CellEditActivateMode.DoubleClick; + uninstallerObjectListView.CellEditUseWholeCell = false; + uninstallerObjectListView.CheckBoxes = true; + uninstallerObjectListView.Columns.AddRange(new ColumnHeader[] { olvColumnDisplayName, olvColumnPublisher, olvColumnRating, olvColumnDisplayVersion, olvColumnInstallDate, olvColumnSize, olvColumnStartup, olvColumnIs64, olvColumnUninstallString, olvColumnAbout, olvColumnInstallSource, olvColumnInstallLocation, olvColumnUninstallerKind, olvColumnSystemComponent, olvColumnStatus, olvColumnProtected, olvColumnRegistryKeyName, olvColumnGuid, olvColumnQuietUninstallString }); + resources.ApplyResources(uninstallerObjectListView, "uninstallerObjectListView"); + uninstallerObjectListView.FullRowSelect = true; uninstallerObjectListView.GridLines = true; uninstallerObjectListView.Name = "uninstallerObjectListView"; uninstallerObjectListView.ShowGroups = false; @@ -403,14 +405,18 @@ private void InitializeComponent() // olvColumnUninstallerKind // resources.ApplyResources(olvColumnUninstallerKind, "olvColumnUninstallerKind"); - // - // olvColumnSystemComponent - // - resources.ApplyResources(olvColumnSystemComponent, "olvColumnSystemComponent"); - // - // olvColumnProtected - // - olvColumnProtected.AspectName = "IsProtected"; + // + // olvColumnSystemComponent + // + resources.ApplyResources(olvColumnSystemComponent, "olvColumnSystemComponent"); + // + // olvColumnStatus + // + resources.ApplyResources(olvColumnStatus, "olvColumnStatus"); + // + // olvColumnProtected + // + olvColumnProtected.AspectName = "IsProtected"; resources.ApplyResources(olvColumnProtected, "olvColumnProtected"); // // olvColumnRegistryKeyName @@ -1601,11 +1607,12 @@ private void InitializeComponent() internal OLVColumn olvColumnInstallSource; internal OLVColumn olvColumnInstallLocation; internal OLVColumn olvColumnUninstallerKind; - internal OLVColumn olvColumnAbout; - internal OLVColumn olvColumnRegistryKeyName; - internal OLVColumn olvColumnSystemComponent; - internal OLVColumn olvColumnQuietUninstallString; - internal OLVColumn olvColumnProtected; + internal OLVColumn olvColumnAbout; + internal OLVColumn olvColumnRegistryKeyName; + internal OLVColumn olvColumnSystemComponent; + internal OLVColumn olvColumnStatus; + internal OLVColumn olvColumnQuietUninstallString; + internal OLVColumn olvColumnProtected; private SaveFileDialog exportDialog; private ContextMenuStrip uninstallListContextMenuStrip; private ToolStripMenuItem uninstallContextMenuStripItem; diff --git a/source/BulkCrapUninstaller/Forms/Windows/MainWindow.resx b/source/BulkCrapUninstaller/Forms/Windows/MainWindow.resx index 155bd31f..692c8b5d 100644 --- a/source/BulkCrapUninstaller/Forms/Windows/MainWindow.resx +++ b/source/BulkCrapUninstaller/Forms/Windows/MainWindow.resx @@ -262,12 +262,18 @@ System Component - - 40 - - - Protected - + + 40 + + + Status + + + 120 + + + Protected + 40 @@ -2261,12 +2267,18 @@ olvColumnSystemComponent - - BrightIdeasSoftware.OLVColumn, ObjectListView, Culture=neutral, PublicKeyToken=null - - - olvColumnProtected - + + BrightIdeasSoftware.OLVColumn, ObjectListView, Culture=neutral, PublicKeyToken=null + + + olvColumnStatus + + + BrightIdeasSoftware.OLVColumn, ObjectListView, Culture=neutral, PublicKeyToken=null + + + olvColumnProtected + BrightIdeasSoftware.OLVColumn, ObjectListView, Culture=neutral, PublicKeyToken=null @@ -3344,4 +3356,4 @@ 17, 60 - \ No newline at end of file + diff --git a/source/BulkCrapUninstaller/Functions/ApplicationList/ApplicationListConstants.cs b/source/BulkCrapUninstaller/Functions/ApplicationList/ApplicationListConstants.cs index 526df84c..5d5cbd1d 100644 --- a/source/BulkCrapUninstaller/Functions/ApplicationList/ApplicationListConstants.cs +++ b/source/BulkCrapUninstaller/Functions/ApplicationList/ApplicationListConstants.cs @@ -3,20 +3,55 @@ Apache License Version 2.0 */ -using System.Drawing; -using BulkCrapUninstaller.Properties; -using UninstallTools; - -namespace BulkCrapUninstaller.Functions.ApplicationList -{ - internal static class ApplicationListConstants - { - public static ApplicationListColors Colors => Settings.Default.MiscColorblind ? ApplicationListColors.ColorBlind : ApplicationListColors.Normal; - - public static Color GetApplicationBackColor(ApplicationUninstallerEntry entry) - { - if (Settings.Default.AdvancedHighlightSpecial) - { +using System; +using System.ComponentModel; +using System.Drawing; +using BulkCrapUninstaller.Controls; +using BulkCrapUninstaller.Properties; +using UninstallTools; +using UninstallToolsLocalisation = UninstallTools.Properties.Localisation; + +namespace BulkCrapUninstaller.Functions.ApplicationList +{ + internal static class ApplicationListConstants + { + private static readonly ComponentResourceManager ListLegendResources = new(typeof(ListLegend)); + + public static ApplicationListColors Colors => Settings.Default.MiscColorblind ? ApplicationListColors.ColorBlind : ApplicationListColors.Normal; + + public static string GetApplicationStatusText(ApplicationUninstallerEntry entry) + { + if (entry == null) return Localisable.Empty; + + if (Settings.Default.AdvancedHighlightSpecial) + { + if (entry.UninstallerKind == UninstallerType.WindowsFeature) + return entry.UninstallerKind.GetLocalisedName(); + + if (entry.UninstallerKind == UninstallerType.StoreApp) + return entry.UninstallerKind.GetLocalisedName(); + + if (entry.IsOrphaned) + return UninstallToolsLocalisation.IsOrphaned; + } + + if (!entry.IsValid && Settings.Default.AdvancedTestInvalid) + return UninstallToolsLocalisation.UninstallStatus_Invalid; + + if (Settings.Default.AdvancedTestCertificates) + { + var result = entry.IsCertificateValid(true); + if (result.HasValue) + return result.Value ? GetListLegendText("labelVerified.Text", "Verified certificate") : GetListLegendText("labelUnverified.Text", "Unverified certificate"); + } + + return Localisable.Empty; + } + + public static Color GetApplicationBackColor(ApplicationUninstallerEntry entry) + { + if (Settings.Default.AdvancedHighlightSpecial) + { if (entry.UninstallerKind == UninstallerType.WindowsFeature) return Colors.WindowsFeatureColor; @@ -64,8 +99,13 @@ public static Color GetApplicationTreemapColor(ApplicationUninstallerEntry entry ? Colors.VerifiedColor : Colors.UnverifiedColor; } - - return Color.White; - } - } -} \ No newline at end of file + + return Color.White; + } + + private static string GetListLegendText(string resourceName, string fallback) + { + return ListLegendResources.GetString(resourceName) ?? fallback; + } + } +} diff --git a/source/BulkCrapUninstaller/Functions/ApplicationList/UninstallerListConfigurator.cs b/source/BulkCrapUninstaller/Functions/ApplicationList/UninstallerListConfigurator.cs index 90be9a53..f21545f0 100644 --- a/source/BulkCrapUninstaller/Functions/ApplicationList/UninstallerListConfigurator.cs +++ b/source/BulkCrapUninstaller/Functions/ApplicationList/UninstallerListConfigurator.cs @@ -201,12 +201,15 @@ public void SetupListView() _reference.olvColumnGuid.AspectGetter = ListViewDelegates.ColumnGuidAspectGetter; _reference.olvColumnGuid.GroupKeyGetter = ListViewDelegates.ColumnGuidGroupKeyGetter; - _reference.olvColumnSystemComponent.AspectName = RegistryFactory.RegistryNameSystemComponent; - _reference.olvColumnSystemComponent.AspectToStringConverter = ListViewDelegates.BoolToYesNoAspectConverter; - _reference.olvColumnSystemComponent.GroupKeyToTitleConverter = ListViewDelegates.BoolToYesNoAspectConverter; - - _reference.olvColumnIs64.AspectGetter = - y => (y as ApplicationUninstallerEntry)?.Is64Bit.GetLocalisedName(); + _reference.olvColumnSystemComponent.AspectName = RegistryFactory.RegistryNameSystemComponent; + _reference.olvColumnSystemComponent.AspectToStringConverter = ListViewDelegates.BoolToYesNoAspectConverter; + _reference.olvColumnSystemComponent.GroupKeyToTitleConverter = ListViewDelegates.BoolToYesNoAspectConverter; + + _reference.olvColumnStatus.AspectGetter = + y => ApplicationListConstants.GetApplicationStatusText(y as ApplicationUninstallerEntry); + + _reference.olvColumnIs64.AspectGetter = + y => (y as ApplicationUninstallerEntry)?.Is64Bit.GetLocalisedName(); _reference.olvColumnProtected.AspectToStringConverter = ListViewDelegates.BoolToYesNoAspectConverter; _reference.olvColumnProtected.GroupKeyToTitleConverter = ListViewDelegates.BoolToYesNoAspectConverter; @@ -267,4 +270,4 @@ public void UpdateColumnFiltering(bool anyUninstallers) _updateThrottleTimer.Start(); } } -} \ No newline at end of file +} diff --git a/source/BulkCrapUninstallerTests/Functions/ApplicationListConstantsTests.cs b/source/BulkCrapUninstallerTests/Functions/ApplicationListConstantsTests.cs new file mode 100644 index 00000000..4e627734 --- /dev/null +++ b/source/BulkCrapUninstallerTests/Functions/ApplicationListConstantsTests.cs @@ -0,0 +1,131 @@ +using BulkCrapUninstaller.Functions.ApplicationList; +using BulkCrapUninstaller.Properties; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using UninstallTools; + +namespace BulkCrapUninstallerTests.Functions +{ + [TestClass] + public class ApplicationListConstantsTests + { + private bool _advancedHighlightSpecial; + private bool _advancedTestInvalid; + private bool _advancedTestCertificates; + + [TestInitialize] + public void TestInitialize() + { + _advancedHighlightSpecial = Settings.Default.AdvancedHighlightSpecial; + _advancedTestInvalid = Settings.Default.AdvancedTestInvalid; + _advancedTestCertificates = Settings.Default.AdvancedTestCertificates; + + Settings.Default.AdvancedHighlightSpecial = true; + Settings.Default.AdvancedTestInvalid = true; + Settings.Default.AdvancedTestCertificates = true; + } + + [TestCleanup] + public void TestCleanup() + { + Settings.Default.AdvancedHighlightSpecial = _advancedHighlightSpecial; + Settings.Default.AdvancedTestInvalid = _advancedTestInvalid; + Settings.Default.AdvancedTestCertificates = _advancedTestCertificates; + } + + [TestMethod] + public void GetApplicationStatusText_ReturnsWindowsFeatureStatus() + { + var entry = new ApplicationUninstallerEntry + { + UninstallerKind = UninstallerType.WindowsFeature, + IsValid = true + }; + + var result = ApplicationListConstants.GetApplicationStatusText(entry); + + Assert.AreEqual(entry.UninstallerKind.GetLocalisedName(), result); + } + + [TestMethod] + public void GetApplicationStatusText_ReturnsStoreAppStatus() + { + var entry = new ApplicationUninstallerEntry + { + UninstallerKind = UninstallerType.StoreApp, + IsValid = true + }; + + var result = ApplicationListConstants.GetApplicationStatusText(entry); + + Assert.AreEqual(entry.UninstallerKind.GetLocalisedName(), result); + } + + [TestMethod] + public void GetApplicationStatusText_ReturnsOrphanedStatus() + { + var entry = new ApplicationUninstallerEntry + { + IsOrphaned = true, + IsValid = true + }; + + var result = ApplicationListConstants.GetApplicationStatusText(entry); + + Assert.AreEqual(UninstallTools.Properties.Localisation.IsOrphaned, result); + } + + [TestMethod] + public void GetApplicationStatusText_ReturnsInvalidStatus() + { + var entry = new ApplicationUninstallerEntry + { + IsValid = false + }; + + var result = ApplicationListConstants.GetApplicationStatusText(entry); + + Assert.AreEqual(UninstallTools.Properties.Localisation.UninstallStatus_Invalid, result); + } + + [TestMethod] + public void GetApplicationStatusText_ReturnsVerifiedCertificateStatus() + { + var entry = new ApplicationUninstallerEntry + { + IsValid = true + }; + entry.SetCertificate(null, true); + + var result = ApplicationListConstants.GetApplicationStatusText(entry); + + Assert.AreEqual("Verified certificate", result); + } + + [TestMethod] + public void GetApplicationStatusText_ReturnsUnverifiedCertificateStatus() + { + var entry = new ApplicationUninstallerEntry + { + IsValid = true + }; + entry.SetCertificate(null, false); + + var result = ApplicationListConstants.GetApplicationStatusText(entry); + + Assert.AreEqual("Unverified certificate", result); + } + + [TestMethod] + public void GetApplicationStatusText_ReturnsEmptyWhenNoSpecialStateApplies() + { + var entry = new ApplicationUninstallerEntry + { + IsValid = true + }; + + var result = ApplicationListConstants.GetApplicationStatusText(entry); + + Assert.AreEqual(Localisable.Empty, result); + } + } +}