From 037b800f4a6d673f163e83e4c121c86f3fe777ac Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 20 May 2025 17:56:24 +0900 Subject: [PATCH 01/19] Add file manager path validation and error handling in SelectFileManagerWindow --- Flow.Launcher.Infrastructure/UserSettings/Settings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 027eb3f926d..f00f42ac095 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -226,8 +226,8 @@ public CustomExplorerViewModel CustomExplorer new() { Name = "Files", - Path = "Files", - DirectoryArgument = "-select \"%d\"", + Path = "Files-Stable", + DirectoryArgument = "\"%d\"", FileArgument = "-select \"%f\"" } }; From 2c7fb93d3710bd4cee3437b7bd4e090d23d37e2a Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 20 May 2025 18:49:38 +0900 Subject: [PATCH 02/19] Add error handling and validation for custom file manager paths --- Flow.Launcher/Languages/en.xaml | 6 ++ Flow.Launcher/PublicAPIInstance.cs | 81 ++++++++++++------- Flow.Launcher/SelectFileManagerWindow.xaml.cs | 56 ++++++++++++- 3 files changed, 113 insertions(+), 30 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 22ab2016cc0..299fe302931 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -373,6 +373,8 @@ File Manager Path Arg For Folder Arg For File + The path for the file manager '{0}' could not be found: {1}\n\nDo you want to continue? + File Manager Path Error Default Web Browser @@ -462,6 +464,10 @@ 1. Upload log file: {0} 2. Copy below exception message + + An error occurred while opening the folder.:\n{0} + Error + Please wait... diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 796f65ae60a..84448a68517 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -316,40 +316,63 @@ public void SavePluginSettings() public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null) { - using var explorer = new Process(); - var explorerInfo = _settings.CustomExplorer; - var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant(); - var targetPath = FileNameOrFilePath is null - ? DirectoryPath - : Path.IsPathRooted(FileNameOrFilePath) - ? FileNameOrFilePath - : Path.Combine(DirectoryPath, FileNameOrFilePath); - - if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer") + try { - // Windows File Manager - // We should ignore and pass only the path to Shell to prevent zombie explorer.exe processes - explorer.StartInfo = new ProcessStartInfo + using var explorer = new Process(); + var explorerInfo = _settings.CustomExplorer; + var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant(); + var targetPath = FileNameOrFilePath is null + ? DirectoryPath + : Path.IsPathRooted(FileNameOrFilePath) + ? FileNameOrFilePath + : Path.Combine(DirectoryPath, FileNameOrFilePath); + + if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer") { - FileName = targetPath, // Not explorer, Only path. - UseShellExecute = true // Must be true to open folder - }; + // Windows File Manager + explorer.StartInfo = new ProcessStartInfo + { + FileName = targetPath, + UseShellExecute = true + }; + } + else + { + // Custom File Manager + explorer.StartInfo = new ProcessStartInfo + { + FileName = explorerInfo.Path.Replace("%d", DirectoryPath), + UseShellExecute = true, + Arguments = FileNameOrFilePath is null + ? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath) + : explorerInfo.FileArgument + .Replace("%d", DirectoryPath) + .Replace("%f", targetPath) + }; + } + + explorer.Start(); } - else + catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 2) { - // Custom File Manager - explorer.StartInfo = new ProcessStartInfo - { - FileName = explorerInfo.Path.Replace("%d", DirectoryPath), - UseShellExecute = true, - Arguments = FileNameOrFilePath is null - ? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath) - : explorerInfo.FileArgument - .Replace("%d", DirectoryPath) - .Replace("%f", targetPath) - }; + // File Manager not found + MessageBoxEx.Show( + string.Format(GetTranslation("fileManagerNotFound"), ex.Message), + GetTranslation("fileManagerNotFoundTitle"), + MessageBoxButton.OK, + MessageBoxImage.Error + ); + } + catch (Exception ex) + { + // Other exceptions + MessageBoxEx.Show( + string.Format(GetTranslation("folderOpenError"), ex.Message), + GetTranslation("errorTitle"), + MessageBoxButton.OK, + MessageBoxImage.Error + ); } - explorer.Start(); } private void OpenUri(Uri uri, bool? inPrivate = null) diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml.cs b/Flow.Launcher/SelectFileManagerWindow.xaml.cs index bf94ddacb01..d2f7ae764e3 100644 --- a/Flow.Launcher/SelectFileManagerWindow.xaml.cs +++ b/Flow.Launcher/SelectFileManagerWindow.xaml.cs @@ -1,5 +1,8 @@ -using System.Collections.ObjectModel; +using System; +using System.Collections.ObjectModel; using System.ComponentModel; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -43,11 +46,62 @@ private void btnCancel_Click(object sender, RoutedEventArgs e) private void btnDone_Click(object sender, RoutedEventArgs e) { + // Check if the selected file manager path is valid + if (!IsFileManagerValid(CustomExplorer.Path)) + { + MessageBoxResult result = MessageBoxEx.Show( + string.Format((string)Application.Current.FindResource("fileManagerPathNotFound"), + CustomExplorer.Name, CustomExplorer.Path), + (string)Application.Current.FindResource("fileManagerPathError"), + MessageBoxButton.YesNo, + MessageBoxImage.Warning); + + if (result == MessageBoxResult.No) + { + return; + } + } + _settings.CustomExplorerList = CustomExplorers.ToList(); _settings.CustomExplorerIndex = SelectedCustomExplorerIndex; Close(); } + private bool IsFileManagerValid(string path) + { + if (string.Equals(path, "explorer", StringComparison.OrdinalIgnoreCase)) + return true; + + if (Path.IsPathRooted(path)) + { + return File.Exists(path); + } + + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "where", + Arguments = path, + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + process.Start(); + string output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + + return !string.IsNullOrEmpty(output); + } + catch + { + return false; + } + } + private void btnAdd_Click(object sender, RoutedEventArgs e) { CustomExplorers.Add(new() From aadfde09d5745c14af96af70227360967b39edd4 Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 20 May 2025 20:32:46 +0900 Subject: [PATCH 03/19] Add tips for file manager usage and improve error messages --- Flow.Launcher/Languages/en.xaml | 10 +++- Flow.Launcher/SelectFileManagerWindow.xaml | 15 ++++-- Flow.Launcher/SelectFileManagerWindow.xaml.cs | 46 +++++++++++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 299fe302931..186f6bd3e2b 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -366,6 +366,8 @@ Select File Manager + Do you use Files? + Depending on the version, Files may use either "Files" or "Files-stable" as its path. (This can vary depending on which version you're using.) For more details, see: Please specify the file location of the file manager you using and add arguments as required. The "%d" represents the directory path to open for, used by the Arg for Folder field and for commands opening specific directories. The "%f" represents the file path to open for, used by the Arg for File field and for commands opening specific files. For example, if the file manager uses a command such as "totalcmd.exe /A c:\windows" to open the c:\windows directory, the File Manager Path will be totalcmd.exe, and the Arg For Folder will be /A "%d". Certain file managers like QTTabBar may just require a path to be supplied, in this instance use "%d" as the File Manager Path and leave the rest of the fileds blank. File Manager @@ -373,7 +375,7 @@ File Manager Path Arg For Folder Arg For File - The path for the file manager '{0}' could not be found: {1}\n\nDo you want to continue? + The path for the file manager '{0}' could not be found: '{1}' Do you want to continue? File Manager Path Error @@ -465,8 +467,12 @@ 2. Copy below exception message - An error occurred while opening the folder.:\n{0} + File Manager Error + + The specified file manager could not be found. Please check the Custom File Manager setting under Settings >General. + Error + An error occurred while opening the folder. {0} Please wait... diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml b/Flow.Launcher/SelectFileManagerWindow.xaml index 0287af9b03a..fbdc2c3b2ae 100644 --- a/Flow.Launcher/SelectFileManagerWindow.xaml +++ b/Flow.Launcher/SelectFileManagerWindow.xaml @@ -73,9 +73,18 @@ +