diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
index d7e87b50b1e..25ceac3bb9c 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
@@ -32,6 +32,8 @@
When enabled, Flow will load programs from the PATH environment variable
Hide app path
For executable files such as UWP or lnk, hide the file path from being visible
+ Hide uninstallers
+ Hides programs with common uninstaller names, such as unins000.exe
Search in Program Description
Flow will search program's description
Suffixes
@@ -92,4 +94,4 @@
This app is not intended to be run as administrator
Unable to run {0}
-
\ No newline at end of file
+
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index e0a7f23dee5..8bf1830e334 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -11,6 +11,7 @@
using Flow.Launcher.Plugin.Program.Views;
using Flow.Launcher.Plugin.Program.Views.Models;
using Microsoft.Extensions.Caching.Memory;
+using Path = System.IO.Path;
using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
namespace Flow.Launcher.Plugin.Program
@@ -33,6 +34,17 @@ public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, I
private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 };
private static MemoryCache cache = new(cacheOptions);
+ private static readonly string[] commonUninstallerNames =
+ {
+ "uninst.exe",
+ "unins000.exe",
+ "uninst000.exe",
+ "uninstall.exe"
+ };
+ // For cases when the uninstaller is named like "Uninstall Program Name.exe"
+ private const string CommonUninstallerPrefix = "uninstall";
+ private const string CommonUninstallerSuffix = ".exe";
+
static Main()
{
}
@@ -52,6 +64,7 @@ public async Task> QueryAsync(Query query, CancellationToken token)
.Concat(_uwps)
.AsParallel()
.WithCancellation(token)
+ .Where(HideUninstallersFilter)
.Where(p => p.Enabled)
.Select(p => p.Result(query.Search, Context.API))
.Where(r => r?.Score > 0)
@@ -68,6 +81,16 @@ public async Task> QueryAsync(Query query, CancellationToken token)
return result;
}
+ private bool HideUninstallersFilter(IProgram program)
+ {
+ if (!_settings.HideUninstallers) return true;
+ if (program is not Win32 win32) return true;
+ var fileName = Path.GetFileName(win32.ExecutablePath);
+ return !commonUninstallerNames.Contains(fileName, StringComparer.OrdinalIgnoreCase) &&
+ !(fileName.StartsWith(CommonUninstallerPrefix, StringComparison.OrdinalIgnoreCase) &&
+ fileName.EndsWith(CommonUninstallerSuffix, StringComparison.OrdinalIgnoreCase));
+ }
+
public async Task InitAsync(PluginInitContext context)
{
Context = context;
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
index ca203f803a7..fb24f64d7d6 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
@@ -102,7 +102,7 @@ private void RemoveRedundantSuffixes()
// CustomSuffixes no longer contains custom suffixes
// users has tweaked the settings
// or this function has been executed once
- if (UseCustomSuffixes == true || ProgramSuffixes == null)
+ if (UseCustomSuffixes == true || ProgramSuffixes == null)
return;
var suffixes = ProgramSuffixes.ToList();
foreach(var item in BuiltinSuffixesStatus)
@@ -117,6 +117,7 @@ private void RemoveRedundantSuffixes()
public bool EnableStartMenuSource { get; set; } = true;
public bool EnableDescription { get; set; } = false;
public bool HideAppsPath { get; set; } = true;
+ public bool HideUninstallers { get; set; } = false;
public bool EnableRegistrySource { get; set; } = true;
public bool EnablePathSource { get; set; } = false;
public bool EnableUWP { get; set; } = true;
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
index fa97de4f26e..e5ca6967e73 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
@@ -85,6 +85,11 @@
Content="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath}"
IsChecked="{Binding HideAppsPath}"
ToolTip="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath_tooltip}" />
+
ProgramSettingDisplayList { get; set; }
public bool EnableDescription
@@ -47,6 +47,16 @@ public bool HideAppsPath
}
}
+ public bool HideUninstallers
+ {
+ get => _settings.HideUninstallers;
+ set
+ {
+ Main.ResetCache();
+ _settings.HideUninstallers = value;
+ }
+ }
+
public bool EnableRegistrySource
{
get => _settings.EnableRegistrySource;