diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
index 3132db36b..eba3c2f79 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
@@ -16,10 +16,14 @@
File Type
Reindex
Indexing
- Index Start Menu
+ Index Sources
+ Options
+ Start Menu
When enabled, Flow will load programs from the start menu
- Index Registry
+ Registry
When enabled, Flow will load programs from the registry
+ PATH
+ 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
Search in Program Description
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index f0a53ed77..2178c8ef5 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -102,7 +102,7 @@ namespace Flow.Launcher.Plugin.Program
var b = Task.Run(() =>
{
- Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexUwpPrograms);
+ Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|UWPPRogram index cost", IndexUwpPrograms);
});
if (cacheEmpty)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
index fbb3ea32c..f927d60cd 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
@@ -11,10 +11,7 @@ using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin.Program.Logger;
using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Plugin.SharedModels;
-using Flow.Launcher.Infrastructure.Logger;
-using System.Collections;
using System.Diagnostics;
-using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
using System.Threading.Channels;
@@ -279,6 +276,14 @@ namespace Flow.Launcher.Plugin.Program.Programs
program.Valid = false;
return program;
}
+ catch (FileNotFoundException e)
+ {
+ ProgramLogger.LogException($"|Win32|LnkProgram|{path}" +
+ "|An unexpected error occurred in the calling method LnkProgram", e);
+
+ program.Valid = false;
+ return program;
+ }
#if !DEBUG //Only do a catch all in production. This is so make developer aware of any unhandled exception and add the exception handling in.
catch (Exception e)
{
@@ -352,14 +357,14 @@ namespace Flow.Launcher.Plugin.Program.Programs
}
}
- private static IEnumerable ProgramPaths(string directory, string[] suffixes)
+ private static IEnumerable ProgramPaths(string directory, string[] suffixes, bool recursive = true)
{
if (!Directory.Exists(directory))
return Enumerable.Empty();
return Directory.EnumerateFiles(directory, "*", new EnumerationOptions
{
- IgnoreInaccessible = true, RecurseSubdirectories = true
+ IgnoreInaccessible = true, RecurseSubdirectories = recursive
}).Where(x => suffixes.Contains(Extension(x)));
}
@@ -395,7 +400,6 @@ namespace Flow.Launcher.Plugin.Program.Programs
private static IEnumerable StartMenuPrograms(string[] suffixes)
{
- var disabledProgramsList = Main._settings.DisabledProgramSources;
var directory1 = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
var directory2 = Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms);
@@ -414,6 +418,29 @@ namespace Flow.Launcher.Plugin.Program.Programs
return programs;
}
+ private static IEnumerable PATHPrograms(string[] suffixes)
+ {
+ var pathEnv = Environment.GetEnvironmentVariable("Path");
+ if (String.IsNullOrEmpty(pathEnv))
+ {
+ return Array.Empty();
+ }
+
+ var paths = pathEnv.Split(";", StringSplitOptions.RemoveEmptyEntries).DistinctBy(p => p.ToLowerInvariant());
+
+ var toFilter = paths.AsParallel().SelectMany(p => ProgramPaths(p, suffixes, recursive: false));
+
+ var programs = ExceptDisabledSource(toFilter.Distinct())
+ .Select(x => Extension(x) switch
+ {
+ ShortcutExtension => LnkProgram(x),
+ UrlExtension => UrlProgram(x),
+ ExeExtension => ExeProgram(x),
+ _ => Win32Program(x)
+ });
+ return programs;
+ }
+
private static IEnumerable AppPathsPrograms(string[] suffixes)
{
// https://msdn.microsoft.com/en-us/library/windows/desktop/ee872121
@@ -566,6 +593,12 @@ namespace Flow.Launcher.Plugin.Program.Programs
autoIndexPrograms = autoIndexPrograms.Concat(startMenu);
}
+ if (settings.EnablePATHSource)
+ {
+ var path = PATHPrograms(settings.GetSuffixes());
+ autoIndexPrograms = autoIndexPrograms.Concat(path);
+ }
+
autoIndexPrograms = ProgramsHasher(autoIndexPrograms);
return programs.Concat(autoIndexPrograms).Where(x => x.Valid).Distinct().ToArray();
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
index 96328ba62..4929d4b09 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
+using PropertyChanged;
using Windows.Foundation.Metadata;
namespace Flow.Launcher.Plugin.Program
@@ -13,7 +14,7 @@ namespace Flow.Launcher.Plugin.Program
public List ProgramSources { get; set; } = new List();
public List DisabledProgramSources { get; set; } = new List();
- [Obsolete, JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ [Obsolete("Should use GetSuffixes() instead."), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string[] ProgramSuffixes { get; set; } = null;
public string[] CustomSuffixes { get; set; } = Array.Empty(); // Custom suffixes only
public string[] CustomProtocols { get; set; } = Array.Empty();
@@ -111,6 +112,8 @@ namespace Flow.Launcher.Plugin.Program
public bool EnableDescription { get; set; } = false;
public bool HideAppsPath { get; set; } = true;
public bool EnableRegistrySource { get; set; } = true;
+ public bool EnablePATHSource { get; set; } = true;
+
public string CustomizedExplorer { get; set; } = Explorer;
public string CustomizedArgs { get; set; } = ExplorerArgs;
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
index f07879465..4d6db38fd 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml
@@ -10,58 +10,88 @@
mc:Ignorable="d">
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
index 1a31e8c28..18e516d6f 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@@ -66,6 +66,16 @@ namespace Flow.Launcher.Plugin.Program.Views
}
}
+ public bool EnablePATHSource
+ {
+ get => _settings.EnablePATHSource;
+ set
+ {
+ _settings.EnablePATHSource = value;
+ ReIndexing();
+ }
+ }
+
public string CustomizedExplorerPath
{
get => _settings.CustomizedExplorer;
@@ -360,4 +370,4 @@ namespace Flow.Launcher.Plugin.Program.Views
}
}
}
-}
\ No newline at end of file
+}