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);
+ }
+ }
+}