CmdPal: Add settings to hide non-apps from results (#45741)

<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR adds new options to the All Apps built-in extension:

- Also include non-app shortcuts from the Start menu
  - Enabled by default
- Also include non-app shortcuts from the desktop
  - Disabled by default

The default states reflect that Start menu shortcuts are largely curated
by installers, and the Start menu itself typically does not surface
non-app items. Desktop shortcuts, on the other hand, are more likely to
be created by the user.

<img width="812" height="499" alt="image"
src="https://github.com/user-attachments/assets/de6c4723-0b52-4606-98fa-469364f5648e"
/>
This commit is contained in:
Jiří Polášek
2026-02-27 21:35:49 +01:00
committed by GitHub
parent f2788f2e09
commit 12fac01ee1
6 changed files with 115 additions and 31 deletions

View File

@@ -13,6 +13,8 @@ public class Settings : ISettingsInterface
private readonly bool enableDesktopSource;
private readonly bool enableRegistrySource;
private readonly bool enablePathEnvironmentVariableSource;
private readonly bool includeNonAppsOnDesktop;
private readonly bool includeNonAppsInStartMenu;
private readonly List<string> programSuffixes;
private readonly List<string> runCommandSuffixes;
@@ -21,6 +23,8 @@ public class Settings : ISettingsInterface
bool enableDesktopSource = true,
bool enableRegistrySource = true,
bool enablePathEnvironmentVariableSource = true,
bool includeNonAppsOnDesktop = false,
bool includeNonAppsInStartMenu = true,
List<string> programSuffixes = null,
List<string> runCommandSuffixes = null)
{
@@ -28,6 +32,8 @@ public class Settings : ISettingsInterface
this.enableDesktopSource = enableDesktopSource;
this.enableRegistrySource = enableRegistrySource;
this.enablePathEnvironmentVariableSource = enablePathEnvironmentVariableSource;
this.includeNonAppsOnDesktop = includeNonAppsOnDesktop;
this.includeNonAppsInStartMenu = includeNonAppsInStartMenu;
this.programSuffixes = programSuffixes ?? new List<string> { "bat", "appref-ms", "exe", "lnk", "url" };
this.runCommandSuffixes = runCommandSuffixes ?? new List<string> { "bat", "appref-ms", "exe", "lnk", "url", "cpl", "msc" };
}
@@ -40,6 +46,10 @@ public class Settings : ISettingsInterface
public bool EnablePathEnvironmentVariableSource => enablePathEnvironmentVariableSource;
public bool IncludeNonAppsOnDesktop => includeNonAppsOnDesktop;
public bool IncludeNonAppsInStartMenu => includeNonAppsInStartMenu;
public List<string> ProgramSuffixes => programSuffixes;
public List<string> RunCommandSuffixes => runCommandSuffixes;

View File

@@ -62,6 +62,10 @@ public class AllAppsSettings : JsonSettingsManager, ISettingsInterface
public bool EnablePathEnvironmentVariableSource => _enablePathEnvironmentVariableSource.Value;
public bool IncludeNonAppsOnDesktop => _includeNonAppsOnDesktop.Value;
public bool IncludeNonAppsInStartMenu => _includeNonAppsInStartMenu.Value;
private readonly ChoiceSetSetting _searchResultLimitSource = new(
Namespaced(nameof(SearchResultLimit)),
Resources.limit_fallback_results_source,
@@ -121,6 +125,18 @@ public class AllAppsSettings : JsonSettingsManager, ISettingsInterface
string.Empty,
false); // this one is very VERY noisy
private readonly ToggleSetting _includeNonAppsOnDesktop = new(
Namespaced(nameof(IncludeNonAppsOnDesktop)),
Resources.include_non_apps_on_desktop,
string.Empty,
false);
private readonly ToggleSetting _includeNonAppsInStartMenu = new(
Namespaced(nameof(IncludeNonAppsInStartMenu)),
Resources.include_non_apps_in_start_menu,
string.Empty,
true);
public double MinScoreThreshold { get; set; } = 0.75;
internal const char SuffixSeparator = ';';
@@ -139,7 +155,9 @@ public class AllAppsSettings : JsonSettingsManager, ISettingsInterface
FilePath = SettingsJsonPath();
Settings.Add(_enableStartMenuSource);
Settings.Add(_includeNonAppsInStartMenu);
Settings.Add(_enableDesktopSource);
Settings.Add(_includeNonAppsOnDesktop);
Settings.Add(_enableRegistrySource);
Settings.Add(_enablePathEnvironmentVariableSource);
Settings.Add(_searchResultLimitSource);

View File

@@ -19,4 +19,8 @@ public interface ISettingsInterface
public List<string> ProgramSuffixes { get; }
public List<string> RunCommandSuffixes { get; }
public bool IncludeNonAppsOnDesktop { get; }
public bool IncludeNonAppsInStartMenu { get; }
}

View File

@@ -409,9 +409,37 @@ public class Win32Program : IProgram
program.Description = info.FileDescription;
}
}
if (program.AppType is ApplicationType.GenericFile or ApplicationType.Folder)
{
var includeNonAppsOnDesktop = AllAppsSettings.Instance.IncludeNonAppsOnDesktop;
var includeNonAppsInStartMenu = AllAppsSettings.Instance.IncludeNonAppsInStartMenu;
var lnk = program.LnkFilePath;
if (!string.IsNullOrEmpty(lnk))
{
var isDesktop = StartsWithFolder(lnk, Environment.SpecialFolder.Desktop) ||
StartsWithFolder(lnk, Environment.SpecialFolder.CommonDesktopDirectory);
var isStartMenu = StartsWithFolder(lnk, Environment.SpecialFolder.StartMenu) ||
StartsWithFolder(lnk, Environment.SpecialFolder.CommonStartMenu);
if ((isDesktop && !includeNonAppsOnDesktop) || (isStartMenu && !includeNonAppsInStartMenu))
{
program.Enabled = false;
}
}
}
}
return program;
static bool StartsWithFolder(string path, Environment.SpecialFolder folder)
{
var folderPath = Environment.GetFolderPath(folder, Environment.SpecialFolderOption.DoNotVerify);
return !string.IsNullOrEmpty(folderPath)
&& path.StartsWith(folderPath, StringComparison.OrdinalIgnoreCase);
}
}
catch (System.IO.FileLoadException e)
{

View File

@@ -106,7 +106,7 @@ namespace Microsoft.CmdPal.Ext.Apps.Properties {
}
/// <summary>
/// Looks up a localized string similar to Include apps registered in the Registry.
/// Looks up a localized string similar to Include apps registered in the Windows Registry.
/// </summary>
internal static string enable_registry_source {
get {
@@ -115,7 +115,7 @@ namespace Microsoft.CmdPal.Ext.Apps.Properties {
}
/// <summary>
/// Looks up a localized string similar to Include apps found in the Start Menu.
/// Looks up a localized string similar to Include apps found in the Start menu.
/// </summary>
internal static string enable_start_menu_source {
get {
@@ -141,6 +141,24 @@ namespace Microsoft.CmdPal.Ext.Apps.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Also include non-app shortcuts from the Start menu.
/// </summary>
internal static string include_non_apps_in_start_menu {
get {
return ResourceManager.GetString("include_non_apps_in_start_menu", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Also include non-app shortcuts from the desktop.
/// </summary>
internal static string include_non_apps_on_desktop {
get {
return ResourceManager.GetString("include_non_apps_on_desktop", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Installed apps.
/// </summary>

View File

@@ -170,13 +170,13 @@
<value>Run as different user</value>
</data>
<data name="enable_start_menu_source" xml:space="preserve">
<value>Include apps found in the Start Menu</value>
<value>Include apps found in the Start menu</value>
</data>
<data name="enable_desktop_source" xml:space="preserve">
<value>Include apps found on the desktop</value>
</data>
<data name="enable_registry_source" xml:space="preserve">
<value>Include apps registered in the Registry</value>
<value>Include apps registered in the Windows Registry</value>
</data>
<data name="enable_path_environment_variable_source" xml:space="preserve">
<value>Include apps anywhere on the %PATH%</value>
@@ -238,4 +238,10 @@
<value>Default ({0})</value>
<comment>default option; {0} = number of items</comment>
</data>
<data name="include_non_apps_on_desktop" xml:space="preserve">
<value>Also include non-app shortcuts from the desktop</value>
</data>
<data name="include_non_apps_in_start_menu" xml:space="preserve">
<value>Also include non-app shortcuts from the Start menu</value>
</data>
</root>