Skip to content

Commit

Permalink
[PT Run] Find applications using the PATH env variable (#4418)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
alekhyareddy28 committed Jun 23, 2020
1 parent 147c08b commit ca99f60
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ private enum ApplicationTypes
{
WEB_APPLICATION = 0,
INTERNET_SHORTCUT_APPLICATION = 1,
WIN32_APPLICATION = 2
WIN32_APPLICATION = 2,
RUN_COMMAND = 3
}

private int Score(string query)
Expand Down Expand Up @@ -116,12 +117,27 @@ public string SetSubtitle(uint AppType, IPublicAPI api)
{
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);
Expand All @@ -144,6 +160,12 @@ public Result Result(string query, IPublicAPI api)
}
}

// 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),
Expand Down Expand Up @@ -431,7 +453,7 @@ private static Win32 ExeProgram(string path)
}
}

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))
{
Expand Down Expand Up @@ -468,6 +490,12 @@ private static IEnumerable<string> ProgramPaths(string directory, string[] suffi

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);
Expand Down Expand Up @@ -518,6 +546,45 @@ private static ParallelQuery<Win32> UnregisteredPrograms(List<Settings.ProgramSo
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;
Expand Down Expand Up @@ -650,8 +717,8 @@ public bool Equals(Win32 app1, Win32 app2)
&& !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;
Expand All @@ -676,7 +743,7 @@ public int GetHashCode(Win32 obj)
// 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();
};
Expand All @@ -702,6 +769,12 @@ public static Win32[] All(Settings settings)
programs = programs.Concat(startMenu);
}

if (settings.EnablePathEnvironmentVariableSource)
{
var appPathEnvironment = PathEnvironmentPrograms(settings.ProgramSuffixes);
programs = programs.Concat(appPathEnvironment);
}

if (settings.EnableDesktopSource)
{
var desktop = DesktopPrograms(settings.ProgramSuffixes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class Settings

public bool EnableRegistrySource { get; set; } = true;

public bool EnablePathEnvironmentVariableSource { get; set; } = true;

internal const char SuffixSeparator = ';';

/// <summary>
Expand Down
40 changes: 40 additions & 0 deletions src/modules/launcher/Wox.Test/Plugins/ProgramPluginTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@ public class ProgramPluginTest
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",
Expand Down Expand Up @@ -293,5 +311,27 @@ public bool PinnedWebPages_ShouldNotBeFiltered_WhenSearchingForThem(string query
// 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));
}
}
}

0 comments on commit ca99f60

Please sign in to comment.