From d1e8bbf9ff398b298cf83cd2e4dfc251d03b03e6 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 01:27:58 +0800 Subject: [PATCH 01/15] Remove toarray() in ProgramsHasher --- Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 6d27e579e88..5352dbb7140 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -553,7 +553,7 @@ private static IEnumerable ProgramsHasher(IEnumerable programs) if (temp.Any()) return DistinctBy(temp, x => x.Description); return g.Take(1); - }).ToArray(); + }); } @@ -589,7 +589,7 @@ public static Win32[] All(Settings settings) autoIndexPrograms = autoIndexPrograms.Concat(path); } - autoIndexPrograms = ProgramsHasher(autoIndexPrograms); + autoIndexPrograms = ProgramsHasher(autoIndexPrograms).ToArray(); return programs.Concat(autoIndexPrograms).Where(x => x.Valid).Distinct().ToArray(); } From d661836cad8dc8badf31c0eb8f24b0105f0bff94 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 14:32:29 +0800 Subject: [PATCH 02/15] re-organize linq --- .../Flow.Launcher.Plugin.Program/Programs/Win32.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 5352dbb7140..7e597b42498 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -379,12 +379,15 @@ private static string Extension(string path) private static IEnumerable UnregisteredPrograms(List sources, string[] suffixes, string[] protocols) { // Disabled custom sources are not in DisabledProgramSources - var paths = ExceptDisabledSource(sources.Where(s => Directory.Exists(s.Location) && s.Enabled) + var paths = sources.Where(s => Directory.Exists(s.Location) && s.Enabled) + .Distinct() .AsParallel() - .SelectMany(s => ProgramPaths(s.Location, suffixes))) - .Distinct(); + .SelectMany(s => ProgramPaths(s.Location, suffixes)); - var programs = paths.Select(x => GetProgramFromPath(x, protocols)); + // Remove disabled programs in DisabledProgramSources + var programs = ExceptDisabledSource(paths) + + .Select(x => GetProgramFromPath(x, protocols)); return programs; } @@ -569,7 +572,7 @@ public static Win32[] All(Settings settings) programs = programs.Concat(unregistered); - var autoIndexPrograms = Enumerable.Empty(); + var autoIndexPrograms = Enumerable.Empty(); // for single programs, not folders if (settings.EnableRegistrySource) { From 3347e9f39e2ed666de503114d77e44689cacb666 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 15:04:09 +0800 Subject: [PATCH 03/15] Refactor --- Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 7e597b42498..067124b2ee4 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -385,7 +385,7 @@ private static IEnumerable UnregisteredPrograms(List sourc .SelectMany(s => ProgramPaths(s.Location, suffixes)); // Remove disabled programs in DisabledProgramSources - var programs = ExceptDisabledSource(paths) + var programs = ExceptDisabledSource(paths).Select(x => GetProgramFromPath(x, protocols)); .Select(x => GetProgramFromPath(x, protocols)); return programs; @@ -418,13 +418,7 @@ private static IEnumerable PATHPrograms(string[] suffixes, string[] proto 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, protocols), - ExeExtension => ExeProgram(x), - _ => Win32Program(x) - }); + .Select(x => GetProgramFromPath(x, protocols)); return programs; } From 519702cd6fd5680054d3203ddf0538cd383db08b Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 15:41:25 +0800 Subject: [PATCH 04/15] handing exception --- .../Programs/Win32.cs | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 067124b2ee4..f54135bebab 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -224,6 +224,15 @@ private static Win32 Win32Program(string path) return Default; } +#if !DEBUG + catch (Exception e) + { + ProgramLogger.LogException($"|Win32|Win32Program|{path}" + + "|An unexpected error occurred in the calling method Win32Program", e); + + return Default; + } +#endif } private static Win32 LnkProgram(string path) @@ -270,16 +279,14 @@ private static Win32 LnkProgram(string path) "|Error caused likely due to trying to get the description of the program", e); - program.Valid = false; - return program; + return Default; } catch (FileNotFoundException e) { ProgramLogger.LogException($"|Win32|LnkProgram|{path}" + "|An unexpected error occurred in the calling method LnkProgram", e); - program.Valid = false; - return program; + return Default; } #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) @@ -287,8 +294,7 @@ private static Win32 LnkProgram(string path) ProgramLogger.LogException($"|Win32|LnkProgram|{path}" + "|An unexpected error occurred in the calling method LnkProgram", e); - program.Valid = false; - return program; + return Default; } #endif } @@ -342,6 +348,13 @@ private static Win32 ExeProgram(string path) program.Description = info.FileDescription; return program; } + catch (FileNotFoundException e) + { + ProgramLogger.LogException($"|Win32|ExeProgram|{path}" + + $"|File not found when trying to load the program from {path}", e); + + return Default; + } catch (Exception e) when (e is SecurityException || e is UnauthorizedAccessException) { ProgramLogger.LogException($"|Win32|ExeProgram|{path}" + @@ -386,8 +399,6 @@ private static IEnumerable UnregisteredPrograms(List sourc // Remove disabled programs in DisabledProgramSources var programs = ExceptDisabledSource(paths).Select(x => GetProgramFromPath(x, protocols)); - - .Select(x => GetProgramFromPath(x, protocols)); return programs; } From 5f85694142073831e074e8874e8f380193590152 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 15:50:54 +0800 Subject: [PATCH 05/15] get common parents for program sources --- .../Programs/Win32.cs | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index f54135bebab..610da2915f0 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -231,7 +231,7 @@ private static Win32 Win32Program(string path) "|An unexpected error occurred in the calling method Win32Program", e); return Default; - } + } #endif } @@ -394,7 +394,7 @@ private static IEnumerable UnregisteredPrograms(List sourc // Disabled custom sources are not in DisabledProgramSources var paths = sources.Where(s => Directory.Exists(s.Location) && s.Enabled) .Distinct() - .AsParallel() + .AsParallel() .SelectMany(s => ProgramPaths(s.Location, suffixes)); // Remove disabled programs in DisabledProgramSources @@ -504,9 +504,6 @@ private static Win32 GetProgramFromPath(string path, string[] protocols) path = Environment.ExpandEnvironmentVariables(path); - if (!File.Exists(path)) - return Default; - return Extension(path) switch { ShortcutExtension => LnkProgram(path), @@ -707,5 +704,27 @@ public static void Dispose() fileSystemWatcher.Dispose(); } } + + private List GetCommonParents(IEnumerable programSources) + { + // To avoid unnecessary io + // like c:\windows and c:\windows\system32 + var grouped = programSources.GroupBy(p => p.Location.ToLowerInvariant()[0]); // group by disk + List result = new(); + foreach (var group in grouped) + { + HashSet parents = group.ToHashSet(); + foreach (var source in group) + { + if (parents.Any(p => source.Location.StartsWith(p.Location, StringComparison.OrdinalIgnoreCase) && + source != p)) + { + parents.Remove(source); + } + } + result.AddRange(parents.Select(x => x.Location)); + } + return result.DistinctBy(x => x.ToLowerInvariant()).ToList(); + } } } From e69926ec442bd516303bfe8610a0a2a0d436d7dd Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 16:02:39 +0800 Subject: [PATCH 06/15] Renaming functions --- .../Programs/Win32.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 610da2915f0..f98b1d7f30e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -364,7 +364,7 @@ private static Win32 ExeProgram(string path) } } - private static IEnumerable ProgramPaths(string directory, string[] suffixes, bool recursive = true) + private static IEnumerable EnmuerateProgramsInDir(string directory, string[] suffixes, bool recursive = true) { if (!Directory.Exists(directory)) return Enumerable.Empty(); @@ -389,13 +389,11 @@ private static string Extension(string path) } } - private static IEnumerable UnregisteredPrograms(List sources, string[] suffixes, string[] protocols) + private static IEnumerable UnregisteredPrograms(List directories, string[] suffixes, string[] protocols) { // Disabled custom sources are not in DisabledProgramSources - var paths = sources.Where(s => Directory.Exists(s.Location) && s.Enabled) - .Distinct() - .AsParallel() - .SelectMany(s => ProgramPaths(s.Location, suffixes)); + var paths = directories.AsParallel() + .SelectMany(s => EnmuerateProgramsInDir(s, suffixes)); // Remove disabled programs in DisabledProgramSources var programs = ExceptDisabledSource(paths).Select(x => GetProgramFromPath(x, protocols)); @@ -406,8 +404,8 @@ private static IEnumerable StartMenuPrograms(string[] suffixes, string[] { var directory1 = Environment.GetFolderPath(Environment.SpecialFolder.Programs); var directory2 = Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms); - var paths1 = ProgramPaths(directory1, suffixes); - var paths2 = ProgramPaths(directory2, suffixes); + var paths1 = EnmuerateProgramsInDir(directory1, suffixes); + var paths2 = EnmuerateProgramsInDir(directory2, suffixes); var toFilter = paths1.Concat(paths2); @@ -426,7 +424,7 @@ private static IEnumerable PATHPrograms(string[] suffixes, string[] proto var paths = pathEnv.Split(";", StringSplitOptions.RemoveEmptyEntries).DistinctBy(p => p.ToLowerInvariant()); - var toFilter = paths.AsParallel().SelectMany(p => ProgramPaths(p, suffixes, recursive: false)); + var toFilter = paths.AsParallel().SelectMany(p => EnmuerateProgramsInDir(p, suffixes, recursive: false)); var programs = ExceptDisabledSource(toFilter.Distinct()) .Select(x => GetProgramFromPath(x, protocols)); @@ -570,7 +568,11 @@ public static Win32[] All(Settings settings) var suffixes = settings.GetSuffixes(); var protocols = settings.GetProtocols(); - var unregistered = UnregisteredPrograms(settings.ProgramSources, suffixes, protocols); + // Disabled custom sources are not in DisabledProgramSources + var sources = settings.ProgramSources.Where(s => Directory.Exists(s.Location) && s.Enabled).Distinct(); + var commonParents = GetCommonParents(sources); + + var unregistered = UnregisteredPrograms(commonParents, suffixes, protocols); programs = programs.Concat(unregistered); @@ -705,7 +707,7 @@ public static void Dispose() } } - private List GetCommonParents(IEnumerable programSources) + private static List GetCommonParents(IEnumerable programSources) { // To avoid unnecessary io // like c:\windows and c:\windows\system32 From fed130b0ce1931c75ab93636bee29b72ab6f81b4 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 16:22:05 +0800 Subject: [PATCH 07/15] Filter common parent for PATH and custom sources --- Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index f98b1d7f30e..61dc146a811 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -414,7 +414,7 @@ private static IEnumerable StartMenuPrograms(string[] suffixes, string[] return programs; } - private static IEnumerable PATHPrograms(string[] suffixes, string[] protocols) + private static IEnumerable PATHPrograms(string[] suffixes, string[] protocols, List commonParents) { var pathEnv = Environment.GetEnvironmentVariable("Path"); if (String.IsNullOrEmpty(pathEnv)) @@ -424,6 +424,8 @@ private static IEnumerable PATHPrograms(string[] suffixes, string[] proto var paths = pathEnv.Split(";", StringSplitOptions.RemoveEmptyEntries).DistinctBy(p => p.ToLowerInvariant()); + paths = paths.Where(x => commonParents.All(parent => !x.StartsWith(parent, StringComparison.OrdinalIgnoreCase))); + var toFilter = paths.AsParallel().SelectMany(p => EnmuerateProgramsInDir(p, suffixes, recursive: false)); var programs = ExceptDisabledSource(toFilter.Distinct()) @@ -592,8 +594,8 @@ public static Win32[] All(Settings settings) if (settings.EnablePATHSource) { - var path = PATHPrograms(settings.GetSuffixes(), protocols); - autoIndexPrograms = autoIndexPrograms.Concat(path); + var path = PATHPrograms(settings.GetSuffixes(), protocols, commonParents); + programs = programs.Concat(path); } autoIndexPrograms = ProgramsHasher(autoIndexPrograms).ToArray(); From 0e18c08798dcc389362c6b567f06eb7734ddb07a Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 16:49:10 +0800 Subject: [PATCH 08/15] non-recursive monitor for custom source --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 2 +- .../Flow.Launcher.Plugin.Program/Programs/Win32.cs | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index c212bf8f446..feeb8e78a24 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) await Task.WhenAll(a, b); Win32.WatchProgramUpdate(_settings); - UWP.WatchPackageChange(); + _ = UWP.WatchPackageChange(); } public static void IndexWin32Programs() diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 61dc146a811..51959143cda 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -396,7 +396,8 @@ private static IEnumerable UnregisteredPrograms(List directories, .SelectMany(s => EnmuerateProgramsInDir(s, suffixes)); // Remove disabled programs in DisabledProgramSources - var programs = ExceptDisabledSource(paths).Select(x => GetProgramFromPath(x, protocols)); + var programs = ExceptDisabledSource(paths) + .Select(x => GetProgramFromPath(x, protocols)); return programs; } @@ -660,13 +661,16 @@ public static void WatchProgramUpdate(Settings settings) if (settings.EnableStartMenuSource) paths.AddRange(GetStartMenuPaths()); - paths.AddRange(from source in settings.ProgramSources where source.Enabled select source.Location); - foreach (var directory in from path in paths where Directory.Exists(path) select path) { WatchDirectory(directory); } + foreach (var directory in from source in settings.ProgramSources where Directory.Exists(source.Location) select source.Location) + { + WatchDirectory(directory, false); + } + _ = Task.Run(MonitorDirectoryChangeAsync); } @@ -685,7 +689,7 @@ public static async Task MonitorDirectoryChangeAsync() } } - public static void WatchDirectory(string directory) + public static void WatchDirectory(string directory, bool recursive = true) { if (!Directory.Exists(directory)) { @@ -696,7 +700,7 @@ public static void WatchDirectory(string directory) watcher.Created += static (_, _) => indexQueue.Writer.TryWrite(default); watcher.Deleted += static (_, _) => indexQueue.Writer.TryWrite(default); watcher.EnableRaisingEvents = true; - watcher.IncludeSubdirectories = true; + watcher.IncludeSubdirectories = recursive; Watchers.Add(watcher); } From e5f82eb0d942a010ca5d08824071a42baa497486 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 16:55:53 +0800 Subject: [PATCH 09/15] Revert "non-recursive monitor for custom source" This reverts commit 0e18c08798dcc389362c6b567f06eb7734ddb07a. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 2 +- .../Flow.Launcher.Plugin.Program/Programs/Win32.cs | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index feeb8e78a24..c212bf8f446 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) await Task.WhenAll(a, b); Win32.WatchProgramUpdate(_settings); - _ = UWP.WatchPackageChange(); + UWP.WatchPackageChange(); } public static void IndexWin32Programs() diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 51959143cda..61dc146a811 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -396,8 +396,7 @@ private static IEnumerable UnregisteredPrograms(List directories, .SelectMany(s => EnmuerateProgramsInDir(s, suffixes)); // Remove disabled programs in DisabledProgramSources - var programs = ExceptDisabledSource(paths) - .Select(x => GetProgramFromPath(x, protocols)); + var programs = ExceptDisabledSource(paths).Select(x => GetProgramFromPath(x, protocols)); return programs; } @@ -661,16 +660,13 @@ public static void WatchProgramUpdate(Settings settings) if (settings.EnableStartMenuSource) paths.AddRange(GetStartMenuPaths()); + paths.AddRange(from source in settings.ProgramSources where source.Enabled select source.Location); + foreach (var directory in from path in paths where Directory.Exists(path) select path) { WatchDirectory(directory); } - foreach (var directory in from source in settings.ProgramSources where Directory.Exists(source.Location) select source.Location) - { - WatchDirectory(directory, false); - } - _ = Task.Run(MonitorDirectoryChangeAsync); } @@ -689,7 +685,7 @@ public static async Task MonitorDirectoryChangeAsync() } } - public static void WatchDirectory(string directory, bool recursive = true) + public static void WatchDirectory(string directory) { if (!Directory.Exists(directory)) { @@ -700,7 +696,7 @@ public static void WatchDirectory(string directory, bool recursive = true) watcher.Created += static (_, _) => indexQueue.Writer.TryWrite(default); watcher.Deleted += static (_, _) => indexQueue.Writer.TryWrite(default); watcher.EnableRaisingEvents = true; - watcher.IncludeSubdirectories = recursive; + watcher.IncludeSubdirectories = true; Watchers.Add(watcher); } From 5f2b94424509e6f491fea50c4305f6e8b3f9bbf7 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 17:39:09 +0800 Subject: [PATCH 10/15] Only watch user specified extensions --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 2 +- .../Flow.Launcher.Plugin.Program/Programs/Win32.cs | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index c212bf8f446..feeb8e78a24 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) await Task.WhenAll(a, b); Win32.WatchProgramUpdate(_settings); - UWP.WatchPackageChange(); + _ = UWP.WatchPackageChange(); } public static void IndexWin32Programs() diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 61dc146a811..03606f028d5 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -660,11 +660,13 @@ public static void WatchProgramUpdate(Settings settings) if (settings.EnableStartMenuSource) paths.AddRange(GetStartMenuPaths()); - paths.AddRange(from source in settings.ProgramSources where source.Enabled select source.Location); + var customSources = GetCommonParents(settings.ProgramSources); + paths.AddRange(customSources); + var fileExtensionToWatch = settings.GetSuffixes(); foreach (var directory in from path in paths where Directory.Exists(path) select path) { - WatchDirectory(directory); + WatchDirectory(directory, fileExtensionToWatch); } _ = Task.Run(MonitorDirectoryChangeAsync); @@ -685,7 +687,7 @@ public static async Task MonitorDirectoryChangeAsync() } } - public static void WatchDirectory(string directory) + public static void WatchDirectory(string directory, string[] extensions) { if (!Directory.Exists(directory)) { @@ -697,6 +699,9 @@ public static void WatchDirectory(string directory) watcher.Deleted += static (_, _) => indexQueue.Writer.TryWrite(default); watcher.EnableRaisingEvents = true; watcher.IncludeSubdirectories = true; + foreach(var extension in extensions) { + watcher.Filters.Add($"*.{extension}"); + } Watchers.Add(watcher); } From 118e100140e502b93f644ad92bbd3d49df5b0302 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 23:16:11 +0800 Subject: [PATCH 11/15] Fix opening containing folder for lnk open parent dir of .lnk instead of its target --- .../Programs/Win32.cs | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 03606f028d5..ac425e0926b 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -25,8 +25,19 @@ public class Win32 : IProgram, IEquatable public string Name { get; set; } public string UniqueIdentifier { get => _uid; set => _uid = value == null ? string.Empty : value.ToLowerInvariant(); } // For path comparison public string IcoPath { get; set; } + /// + /// Path of the file. It's the path of .lnk or .url for .lnk and .url. + /// public string FullPath { get; set; } + /// + /// Path of the excutable for .lnk, or the URL for .url. + /// public string LnkResolvedPath { get; set; } + /// + /// Path of the actual executable file. + /// + public string ExecutablePath => LnkResolvedPath ?? FullPath; + public string WorkingDir => Directory.GetParent(ExecutablePath)?.FullName ?? string.Empty; public string ParentDirectory { get; set; } public string ExecutableName { get; set; } public string Description { get; set; } @@ -97,10 +108,23 @@ public Result Result(string query, IPublicAPI api) matchResult.MatchData = new List(); } + string subtitle = string.Empty; + if (!Main._settings.HideAppsPath) + { + if (Extension(FullPath) == UrlExtension) + { + subtitle = LnkResolvedPath; + } + else + { + subtitle = FullPath; + } + } + var result = new Result { Title = title, - SubTitle = Main._settings.HideAppsPath ? string.Empty : LnkResolvedPath ?? FullPath, + SubTitle = subtitle, IcoPath = IcoPath, Score = matchResult.Score, TitleHighlightData = matchResult.MatchData, @@ -116,8 +140,8 @@ public Result Result(string query, IPublicAPI api) var info = new ProcessStartInfo { - FileName = LnkResolvedPath ?? FullPath, - WorkingDirectory = ParentDirectory, + FileName = ExecutablePath, + WorkingDirectory = WorkingDir, UseShellExecute = true, Verb = runAsAdmin ? "runas" : null }; @@ -143,8 +167,8 @@ public List ContextMenus(IPublicAPI api) { var info = new ProcessStartInfo { - FileName = FullPath, - WorkingDirectory = ParentDirectory, + FileName = ExecutablePath, + WorkingDirectory = WorkingDir, UseShellExecute = true }; @@ -162,8 +186,8 @@ public List ContextMenus(IPublicAPI api) { var info = new ProcessStartInfo { - FileName = FullPath, - WorkingDirectory = ParentDirectory, + FileName = ExecutablePath, + WorkingDirectory = WorkingDir, Verb = "runas", UseShellExecute = true }; @@ -250,8 +274,7 @@ private static Win32 LnkProgram(string path) var extension = Extension(target); if (extension == ExeExtension && File.Exists(target)) { - program.LnkResolvedPath = program.FullPath; - program.FullPath = Path.GetFullPath(target).ToLowerInvariant(); + program.LnkResolvedPath = Path.GetFullPath(target); program.ExecutableName = Path.GetFileName(target); var description = _helper.description; @@ -550,7 +573,7 @@ public static IEnumerable DistinctBy(IEnumerable source, Func private static IEnumerable ProgramsHasher(IEnumerable programs) { - return programs.GroupBy(p => p.FullPath.ToLowerInvariant()) + return programs.GroupBy(p => p.ExecutablePath.ToLowerInvariant()) .AsParallel() .SelectMany(g => { From b120c2358bda56b1978c8486d9ef96894af2f38a Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Thu, 17 Nov 2022 23:22:12 +0800 Subject: [PATCH 12/15] Adjust text for protocol tooltip Try to avoid situation like http matches https --- Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml index 1c6c97792a9..ec9b41889a9 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml @@ -61,7 +61,7 @@ Insert file suffixes you want to index. Suffixes should be separated by ';'. (ex>bat;py) - Insert protocols of .url files you want to index. Protocols should be separated by ';'. (ex>ftp;netflix) + Insert protocols of .url files you want to index. Protocols should be separated by ';', and should end with "//". (ex>ftp://;mailto://) Run As Different User From 8bac95db662251d579b3c64817d6cbb469f1ddf9 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 18 Nov 2022 01:16:57 +0800 Subject: [PATCH 13/15] fix typo --- Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml | 2 +- Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml index ec9b41889a9..6d9f916e173 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml @@ -61,7 +61,7 @@ Insert file suffixes you want to index. Suffixes should be separated by ';'. (ex>bat;py) - Insert protocols of .url files you want to index. Protocols should be separated by ';', and should end with "//". (ex>ftp://;mailto://) + Insert protocols of .url files you want to index. Protocols should be separated by ';', and should end with "://". (ex>ftp://;mailto://) Run As Different User diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index ac425e0926b..2b4e81bc408 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -387,7 +387,7 @@ private static Win32 ExeProgram(string path) } } - private static IEnumerable EnmuerateProgramsInDir(string directory, string[] suffixes, bool recursive = true) + private static IEnumerable EnumerateProgramsInDir(string directory, string[] suffixes, bool recursive = true) { if (!Directory.Exists(directory)) return Enumerable.Empty(); @@ -416,7 +416,7 @@ private static IEnumerable UnregisteredPrograms(List directories, { // Disabled custom sources are not in DisabledProgramSources var paths = directories.AsParallel() - .SelectMany(s => EnmuerateProgramsInDir(s, suffixes)); + .SelectMany(s => EnumerateProgramsInDir(s, suffixes)); // Remove disabled programs in DisabledProgramSources var programs = ExceptDisabledSource(paths).Select(x => GetProgramFromPath(x, protocols)); @@ -427,8 +427,8 @@ private static IEnumerable StartMenuPrograms(string[] suffixes, string[] { var directory1 = Environment.GetFolderPath(Environment.SpecialFolder.Programs); var directory2 = Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms); - var paths1 = EnmuerateProgramsInDir(directory1, suffixes); - var paths2 = EnmuerateProgramsInDir(directory2, suffixes); + var paths1 = EnumerateProgramsInDir(directory1, suffixes); + var paths2 = EnumerateProgramsInDir(directory2, suffixes); var toFilter = paths1.Concat(paths2); @@ -449,7 +449,7 @@ private static IEnumerable PATHPrograms(string[] suffixes, string[] proto paths = paths.Where(x => commonParents.All(parent => !x.StartsWith(parent, StringComparison.OrdinalIgnoreCase))); - var toFilter = paths.AsParallel().SelectMany(p => EnmuerateProgramsInDir(p, suffixes, recursive: false)); + var toFilter = paths.AsParallel().SelectMany(p => EnumerateProgramsInDir(p, suffixes, recursive: false)); var programs = ExceptDisabledSource(toFilter.Distinct()) .Select(x => GetProgramFromPath(x, protocols)); From db8ba91558c88525836464723db9d35155cca253 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 18 Nov 2022 01:39:42 +0800 Subject: [PATCH 14/15] Fix subpath --- .../Programs/Win32.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 2b4e81bc408..d9c26435aa0 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -737,6 +737,17 @@ public static void Dispose() } } + // https://stackoverflow.com/a/66877016 + private static bool IsSubPathOf(string subPath, string basePath) + { + var rel = Path.GetRelativePath(basePath, subPath); + return rel != "." + && rel != ".." + && !rel.StartsWith("../") + && !rel.StartsWith(@"..\") + && !Path.IsPathRooted(rel); + } + private static List GetCommonParents(IEnumerable programSources) { // To avoid unnecessary io @@ -748,8 +759,8 @@ private static List GetCommonParents(IEnumerable programS HashSet parents = group.ToHashSet(); foreach (var source in group) { - if (parents.Any(p => source.Location.StartsWith(p.Location, StringComparison.OrdinalIgnoreCase) && - source != p)) + if (parents.Any(p => IsSubPathOf(source.Location, p.Location) && + source != p)) // TODO startwith not accurate { parents.Remove(source); } From 9dcf030e8abfa3405dee158c4defd51fe41c0090 Mon Sep 17 00:00:00 2001 From: Vic <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 18 Nov 2022 01:42:15 +0800 Subject: [PATCH 15/15] formatting --- .../Flow.Launcher.Plugin.Program/Programs/Win32.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index d9c26435aa0..25ac2b213d6 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -440,9 +440,9 @@ private static IEnumerable StartMenuPrograms(string[] suffixes, string[] private static IEnumerable PATHPrograms(string[] suffixes, string[] protocols, List commonParents) { var pathEnv = Environment.GetEnvironmentVariable("Path"); - if (String.IsNullOrEmpty(pathEnv)) - { - return Array.Empty(); + if (String.IsNullOrEmpty(pathEnv)) + { + return Array.Empty(); } var paths = pathEnv.Split(";", StringSplitOptions.RemoveEmptyEntries).DistinctBy(p => p.ToLowerInvariant()); @@ -722,7 +722,8 @@ public static void WatchDirectory(string directory, string[] extensions) watcher.Deleted += static (_, _) => indexQueue.Writer.TryWrite(default); watcher.EnableRaisingEvents = true; watcher.IncludeSubdirectories = true; - foreach(var extension in extensions) { + foreach (var extension in extensions) + { watcher.Filters.Add($"*.{extension}"); } @@ -760,7 +761,7 @@ private static List GetCommonParents(IEnumerable programS foreach (var source in group) { if (parents.Any(p => IsSubPathOf(source.Location, p.Location) && - source != p)) // TODO startwith not accurate + source != p)) { parents.Remove(source); }