diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
index 3132db36bf4..eba3c2f7956 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 f0a53ed7758..2178c8ef5cd 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -102,7 +102,7 @@ public async Task InitAsync(PluginInitContext context)
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 fbb3ea32cb4..f927d60cd28 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.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 @@ private static Win32 LnkProgram(string path)
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 @@ private static Win32 ExeProgram(string path)
}
}
- 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 @@ private static IEnumerable UnregisteredPrograms(List 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 @@ private static IEnumerable StartMenuPrograms(string[] suffixes)
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 @@ public static Win32[] All(Settings settings)
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 96328ba62eb..4929d4b09e3 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
@@ -3,6 +3,7 @@
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 @@ public class Settings
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 @@ private void RemoveRedundantSuffixes()
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 f078794654b..4d6db38fdb1 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 1a31e8c2833..18e516d6fc3 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 @@ public bool EnableStartMenuSource
}
}
+ public bool EnablePATHSource
+ {
+ get => _settings.EnablePATHSource;
+ set
+ {
+ _settings.EnablePATHSource = value;
+ ReIndexing();
+ }
+ }
+
public string CustomizedExplorerPath
{
get => _settings.CustomizedExplorer;
@@ -360,4 +370,4 @@ private void Row_OnClick(object sender, RoutedEventArgs e)
}
}
}
-}
\ No newline at end of file
+}