mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-12 18:29:24 +08:00
[PT Run] Find applications using the PATH env variable (#4418)
* Search for programs in the path env variable * removing list of disabled programs * Added env variable string to classify apps * reverted the fullpath change * removing full paths while calculating dups * removed dups * removed debugging code * Renamed to run command * Added condition to filter run commands unless there is an exact match * renamed occurances to RUN COMMAND * localized the subtitle - Run command * Added tests * add fullpath back to hash calculation * renamed the function
This commit is contained in:
parent
147c08bd71
commit
ca99f60964
@ -38,5 +38,6 @@
|
||||
<system:String x:Key="powertoys_run_plugin_program_win32_application">Win32-Anwendung</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_internet_shortcut_application">Weblink-Anwendung</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_web_application">Web-Anwendung</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_run_command">Run command</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
@ -49,4 +49,5 @@
|
||||
<system:String x:Key="powertoys_run_plugin_program_win32_application">Win32 application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_internet_shortcut_application">Internet shortcut application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_web_application">Web application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_run_command">Run command</system:String>
|
||||
</ResourceDictionary>
|
@ -39,5 +39,6 @@
|
||||
<system:String x:Key="powertoys_run_plugin_program_win32_application">Win32 application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_internet_shortcut_application">Internet shortcut application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_web_application">Web application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_run_command">Run command</system:String>
|
||||
|
||||
</ResourceDictionary>
|
@ -38,5 +38,6 @@
|
||||
<system:String x:Key="powertoys_run_plugin_program_win32_application">Win32 application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_internet_shortcut_application">Internet shortcut application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_web_application">Web application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_run_command">Run command</system:String>
|
||||
|
||||
</ResourceDictionary>
|
@ -40,5 +40,6 @@
|
||||
<system:String x:Key="powertoys_run_plugin_program_win32_application">Win32 application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_internet_shortcut_application">Internet shortcut application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_web_application">Web application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_run_command">Run command</system:String>
|
||||
|
||||
</ResourceDictionary>
|
@ -40,5 +40,6 @@
|
||||
<system:String x:Key="powertoys_run_plugin_program_win32_application">Win32 application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_internet_shortcut_application">Internet shortcut application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_web_application">Web application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_run_command">Run command</system:String>
|
||||
|
||||
</ResourceDictionary>
|
@ -38,4 +38,6 @@
|
||||
<system:String x:Key="powertoys_run_plugin_program_win32_application">Win32 application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_internet_shortcut_application">Internet shortcut application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_web_application">Web application</system:String>
|
||||
<system:String x:Key="powertoys_run_plugin_program_run_command">Run command</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
@ -48,7 +48,8 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
WEB_APPLICATION = 0,
|
||||
INTERNET_SHORTCUT_APPLICATION = 1,
|
||||
WIN32_APPLICATION = 2
|
||||
WIN32_APPLICATION = 2,
|
||||
RUN_COMMAND = 3
|
||||
}
|
||||
|
||||
private int Score(string query)
|
||||
@ -116,12 +117,27 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
return api.GetTranslation("powertoys_run_plugin_program_web_application");
|
||||
}
|
||||
else if(AppType == (uint)ApplicationTypes.RUN_COMMAND)
|
||||
{
|
||||
return api.GetTranslation("powertoys_run_plugin_program_run_command");
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public bool QueryEqualsNameForRunCommands(string query)
|
||||
{
|
||||
if (AppType == (uint)ApplicationTypes.RUN_COMMAND
|
||||
&& !query.Equals(Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Result Result(string query, IPublicAPI api)
|
||||
{
|
||||
var score = Score(query);
|
||||
@ -144,6 +160,12 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This is to display run commands only when there is an exact match, like in start menu
|
||||
if(!QueryEqualsNameForRunCommands(query))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var result = new Result
|
||||
{
|
||||
SubTitle = SetSubtitle(AppType, api),
|
||||
@ -431,7 +453,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<string> ProgramPaths(string directory, string[] suffixes)
|
||||
private static IEnumerable<string> ProgramPaths(string directory, string[] suffixes, bool recursiveSearch = true)
|
||||
{
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
@ -468,6 +490,12 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
|
||||
try
|
||||
{
|
||||
// If the search is set to be non-recursive, then do not enqueue the child directories.
|
||||
if(!recursiveSearch)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var childDirectory in Directory.EnumerateDirectories(currentDirectory, "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
folderQueue.Enqueue(childDirectory);
|
||||
@ -518,6 +546,45 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
return programs1.Concat(programs2).Concat(programs3);
|
||||
}
|
||||
|
||||
|
||||
// Function to obtain the list of applications, the locations of which have been added to the env variable PATH
|
||||
private static ParallelQuery<Win32> PathEnvironmentPrograms(string[] suffixes)
|
||||
{
|
||||
|
||||
// To get all the locations stored in the PATH env variable
|
||||
var pathEnvVariable = Environment.GetEnvironmentVariable("PATH");
|
||||
string[] searchPaths = pathEnvVariable.Split(Path.PathSeparator);
|
||||
IEnumerable<String> toFilterAllPaths = new List<String>();
|
||||
bool isRecursiveSearch = true;
|
||||
|
||||
foreach(string path in searchPaths)
|
||||
{
|
||||
if(path.Length > 0)
|
||||
{
|
||||
// to expand any environment variables present in the path
|
||||
string directory = Environment.ExpandEnvironmentVariables(path);
|
||||
var paths = ProgramPaths(directory, suffixes, !isRecursiveSearch);
|
||||
toFilterAllPaths = toFilterAllPaths.Concat(paths);
|
||||
}
|
||||
}
|
||||
|
||||
var allPaths = toFilterAllPaths
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
var programs1 = allPaths.AsParallel().Where(p => Extension(p).Equals(ShortcutExtension, StringComparison.OrdinalIgnoreCase)).Select(LnkProgram);
|
||||
var programs2 = allPaths.AsParallel().Where(p => Extension(p).Equals(ApplicationReferenceExtension, StringComparison.OrdinalIgnoreCase)).Select(Win32Program);
|
||||
var programs3 = allPaths.AsParallel().Where(p => Extension(p).Equals(InternetShortcutExtension, StringComparison.OrdinalIgnoreCase)).Select(InternetShortcutProgram);
|
||||
var programs4 = allPaths.AsParallel().Where(p => Extension(p).Equals(ExeExtension, StringComparison.OrdinalIgnoreCase)).Select(ExeProgram);
|
||||
|
||||
var allPrograms = programs1.Concat(programs2).Where(p => p.Valid)
|
||||
.Concat(programs3).Where(p => p.Valid)
|
||||
.Concat(programs4).Where(p => p.Valid)
|
||||
.Select( p => { p.AppType = (uint)ApplicationTypes.RUN_COMMAND; return p; });
|
||||
|
||||
return allPrograms;
|
||||
}
|
||||
|
||||
private static ParallelQuery<Win32> IndexPath(string[] suffixes, List<string> IndexLocation)
|
||||
{
|
||||
var disabledProgramsList = Main._settings.DisabledProgramSources;
|
||||
@ -650,8 +717,8 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
&& !string.IsNullOrEmpty(app1.ExecutableName) && !string.IsNullOrEmpty(app2.ExecutableName)
|
||||
&& !string.IsNullOrEmpty(app1.FullPath) && !string.IsNullOrEmpty(app2.FullPath))
|
||||
{
|
||||
return app1.Name.Equals(app2.Name, StringComparison.OrdinalIgnoreCase)
|
||||
&& app1.ExecutableName.Equals(app2.ExecutableName, StringComparison.OrdinalIgnoreCase)
|
||||
return app1.Name.Equals(app2.Name, StringComparison.OrdinalIgnoreCase)
|
||||
&& app1.ExecutableName.Equals(app2.ExecutableName, StringComparison.OrdinalIgnoreCase)
|
||||
&& app1.FullPath.Equals(app2.FullPath, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
return false;
|
||||
@ -676,7 +743,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
// Deduplication code
|
||||
public static Func<ParallelQuery<Win32>, Win32[]> DeduplicatePrograms = (programs) =>
|
||||
{
|
||||
var uniqueExePrograms = programs.Where(x => !string.IsNullOrEmpty(x.LnkResolvedPath) || Extension(x.FullPath) != ExeExtension);
|
||||
var uniqueExePrograms = programs.Where(x => !(string.IsNullOrEmpty(x.LnkResolvedPath) && (Extension(x.FullPath) == ExeExtension) && !(x.AppType == (uint)ApplicationTypes.RUN_COMMAND)));
|
||||
var uniquePrograms = uniqueExePrograms.Distinct(new removeDuplicatesComparer());
|
||||
return uniquePrograms.ToArray();
|
||||
};
|
||||
@ -702,6 +769,12 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
programs = programs.Concat(startMenu);
|
||||
}
|
||||
|
||||
if (settings.EnablePathEnvironmentVariableSource)
|
||||
{
|
||||
var appPathEnvironment = PathEnvironmentPrograms(settings.ProgramSuffixes);
|
||||
programs = programs.Concat(appPathEnvironment);
|
||||
}
|
||||
|
||||
if (settings.EnableDesktopSource)
|
||||
{
|
||||
var desktop = DesktopPrograms(settings.ProgramSuffixes);
|
||||
|
@ -17,6 +17,8 @@ namespace Microsoft.Plugin.Program
|
||||
|
||||
public bool EnableRegistrySource { get; set; } = true;
|
||||
|
||||
public bool EnablePathEnvironmentVariableSource { get; set; } = true;
|
||||
|
||||
internal const char SuffixSeparator = ';';
|
||||
|
||||
/// <summary>
|
||||
|
@ -126,6 +126,24 @@ namespace Wox.Test.Plugins
|
||||
LnkResolvedPath = "c:\\programdata\\microsoft\\windows\\start menu\\programs\\test proxy.lnk"
|
||||
};
|
||||
|
||||
Win32 cmd_run_command = new Win32
|
||||
{
|
||||
Name = "cmd",
|
||||
ExecutableName = "cmd.exe",
|
||||
FullPath = "c:\\windows\\system32\\cmd.exe",
|
||||
LnkResolvedPath = null,
|
||||
AppType = 3 // Run command
|
||||
};
|
||||
|
||||
Win32 cmder_run_command = new Win32
|
||||
{
|
||||
Name = "Cmder",
|
||||
ExecutableName = "Cmder.exe",
|
||||
FullPath = "c:\\tools\\cmder\\cmder.exe",
|
||||
LnkResolvedPath = null,
|
||||
AppType = 3 // Run command
|
||||
};
|
||||
|
||||
Win32 dummy_internetShortcut_app = new Win32
|
||||
{
|
||||
Name = "Shop Titans",
|
||||
@ -293,5 +311,27 @@ namespace Wox.Test.Plugins
|
||||
// unreachable code
|
||||
return true;
|
||||
}
|
||||
|
||||
[TestCase("Command Prompt")]
|
||||
[TestCase("cmd")]
|
||||
[TestCase("cmd.exe")]
|
||||
[TestCase("ignoreQueryText")]
|
||||
public void Win32Applications_ShouldNotBeFiltered_WhenFilteringRunCommands(string query)
|
||||
{
|
||||
// Even if there is an exact match in the name or exe name, win32 applications should never be filtered
|
||||
Assert.IsTrue(command_prompt.QueryEqualsNameForRunCommands(query));
|
||||
}
|
||||
|
||||
[TestCase("cmd")]
|
||||
[TestCase("Cmd")]
|
||||
[TestCase("CMD")]
|
||||
public void RunCommands_ShouldNotBeFiltered_OnExactMatch(string query)
|
||||
{
|
||||
// Partial matches should be filtered as cmd is not equal to cmder
|
||||
Assert.IsFalse(cmder_run_command.QueryEqualsNameForRunCommands(query));
|
||||
|
||||
// the query matches the name (cmd) and is therefore not filtered (case-insensitive)
|
||||
Assert.IsTrue(cmd_run_command.QueryEqualsNameForRunCommands(query));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user