From c11d78ca69a2e0d9932dc5c11352e7ec658141d1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 25 Feb 2025 11:46:22 +0800 Subject: [PATCH 1/8] Fix dispatcher thread issue in dependency injection --- Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/PublicAPIInstance.cs | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 952ca70c458..d03a423f8d1 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -102,8 +102,8 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => await imageLoadertask; var mainVM = Ioc.Default.GetRequiredService(); + ((PublicAPIInstance)API).Initialize(mainVM); var window = new MainWindow(_settings, mainVM); - Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}"); Current.MainWindow = window; diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 1a08150e591..207a3150b90 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -34,17 +34,22 @@ namespace Flow.Launcher public class PublicAPIInstance : IPublicAPI { private readonly Settings _settings; - private readonly MainViewModel _mainVM; + private MainViewModel _mainVM; - #region Constructor + #region Constructor & Initialization - public PublicAPIInstance(Settings settings, MainViewModel mainVM) + public PublicAPIInstance(Settings settings) { _settings = settings; - _mainVM = mainVM; GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } + + // We must initialize mainVM later to avoid dispatcher thread issue + public void Initialize(MainViewModel mainVM) + { + _mainVM = mainVM; + } #endregion From 18290b8d26bcc5b2924c1f613220f42141581068 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 10:52:47 +0800 Subject: [PATCH 2/8] Add exception when app constructor failed --- Flow.Launcher/App.xaml.cs | 63 ++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 94a1b87e1ce..b42d5128c17 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -35,31 +35,52 @@ public partial class App : IDisposable, ISingleInstanceApp public App() { // Initialize settings - var storage = new FlowLauncherJsonStorage(); - _settings = storage.Load(); - _settings.SetStorage(storage); - _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); + try + { + var storage = new FlowLauncherJsonStorage(); + _settings = storage.Load(); + _settings.SetStorage(storage); + _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); + } + catch (Exception e) + { + MessageBoxEx.Show($"Cannot load setting storage: {e}"); + } // Configure the dependency injection container - var host = Host.CreateDefaultBuilder() - .UseContentRoot(AppContext.BaseDirectory) - .ConfigureServices(services => services - .AddSingleton(_ => _settings) - .AddSingleton(sp => new Updater(sp.GetRequiredService(), Launcher.Properties.Settings.Default.GithubRepo)) - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - ).Build(); - Ioc.Default.ConfigureServices(host.Services); + try + { + var host = Host.CreateDefaultBuilder() + .UseContentRoot(AppContext.BaseDirectory) + .ConfigureServices(services => services + .AddSingleton(_ => _settings) + .AddSingleton(sp => new Updater(sp.GetRequiredService(), Launcher.Properties.Settings.Default.GithubRepo)) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + ).Build(); + Ioc.Default.ConfigureServices(host.Services); + } + catch (Exception e) + { + MessageBoxEx.Show($"Cannot configure dependency injection container: {e}"); + } // Initialize the public API and Settings first - API = Ioc.Default.GetRequiredService(); - _settings.Initialize(); + try + { + API = Ioc.Default.GetRequiredService(); + _settings.Initialize(); + } + catch (Exception e) + { + MessageBoxEx.Show($"Cannot initialize public API and settings: {e}"); + } } [STAThread] From d8b07f6919556cb416413cbef6303d7dafd8d4aa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 11:19:29 +0800 Subject: [PATCH 3/8] Use message box instead --- Flow.Launcher/App.xaml.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index b42d5128c17..836399021bb 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -44,7 +44,7 @@ public App() } catch (Exception e) { - MessageBoxEx.Show($"Cannot load setting storage: {e}"); + MessageBox.Show($"Cannot load setting storage: {e}"); } // Configure the dependency injection container @@ -68,7 +68,7 @@ public App() } catch (Exception e) { - MessageBoxEx.Show($"Cannot configure dependency injection container: {e}"); + MessageBox.Show($"Cannot configure dependency injection container: {e}"); } // Initialize the public API and Settings first @@ -79,7 +79,7 @@ public App() } catch (Exception e) { - MessageBoxEx.Show($"Cannot initialize public API and settings: {e}"); + MessageBox.Show($"Cannot initialize public API and settings: {e}"); } } From 92df02115ec4e411736feef95498886a29b0a7bc Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 11:36:38 +0800 Subject: [PATCH 4/8] Improve message box in app constructor --- Flow.Launcher/App.xaml.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 836399021bb..4044f325571 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -44,7 +44,8 @@ public App() } catch (Exception e) { - MessageBox.Show($"Cannot load setting storage: {e}"); + ShowErrorMsgBox("Cannot load setting storage, please check local data directory", e); + return; } // Configure the dependency injection container @@ -68,7 +69,8 @@ public App() } catch (Exception e) { - MessageBox.Show($"Cannot configure dependency injection container: {e}"); + ShowErrorMsgBox("Cannot configure dependency injection container, please open new issue in Flow.Launcher", e); + return; } // Initialize the public API and Settings first @@ -79,10 +81,16 @@ public App() } catch (Exception e) { - MessageBox.Show($"Cannot initialize public API and settings: {e}"); + ShowErrorMsgBox("Cannot initialize api and settings, please open new issue in Flow.Launcher", e); + return; } } + private static void ShowErrorMsgBox(string caption, Exception e) + { + MessageBox.Show(e.ToString(), caption, MessageBoxButton.OK, MessageBoxImage.Error); + } + [STAThread] public static void Main() { From b61199a5e3ea97fce84003de83756ca150d38be6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 12:02:19 +0800 Subject: [PATCH 5/8] Fail fast to exit Flow when encountering issue in constructor --- Flow.Launcher/App.xaml.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 4044f325571..54710ec425d 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -44,7 +44,7 @@ public App() } catch (Exception e) { - ShowErrorMsgBox("Cannot load setting storage, please check local data directory", e); + ShowErrorMsgBoxAndFailFast("Cannot load setting storage, please check local data directory", e); return; } @@ -69,7 +69,7 @@ public App() } catch (Exception e) { - ShowErrorMsgBox("Cannot configure dependency injection container, please open new issue in Flow.Launcher", e); + ShowErrorMsgBoxAndFailFast("Cannot configure dependency injection container, please open new issue in Flow.Launcher", e); return; } @@ -81,14 +81,18 @@ public App() } catch (Exception e) { - ShowErrorMsgBox("Cannot initialize api and settings, please open new issue in Flow.Launcher", e); + ShowErrorMsgBoxAndFailFast("Cannot initialize api and settings, please open new issue in Flow.Launcher", e); return; } } - private static void ShowErrorMsgBox(string caption, Exception e) + private static void ShowErrorMsgBoxAndFailFast(string message, Exception e) { - MessageBox.Show(e.ToString(), caption, MessageBoxButton.OK, MessageBoxImage.Error); + // Firstly show users the message + MessageBox.Show(e.ToString(), message, MessageBoxButton.OK, MessageBoxImage.Error); + + // Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info. + Environment.FailFast(message, e); } [STAThread] From d48b4dff20bb806b764a26e0c14b0fedd2f2795f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 14:37:27 +0800 Subject: [PATCH 6/8] Downgrade dependency injection version --- Flow.Launcher/Flow.Launcher.csproj | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 0baa1bef503..b9c53fa1316 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -91,8 +91,9 @@ - - + + + all From 437b1c012414e7064a87dfe2eac9c78c01a57cb8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 14:43:46 +0800 Subject: [PATCH 7/8] Revert "Downgrade dependency injection version" This reverts commit d48b4dff20bb806b764a26e0c14b0fedd2f2795f. --- Flow.Launcher/Flow.Launcher.csproj | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index b9c53fa1316..0baa1bef503 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -91,9 +91,8 @@ - - - + + all From 14342574d724a59b9a0acd384ac517bb8a7de61b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 14:48:59 +0800 Subject: [PATCH 8/8] Remove auto startup position --- .../AutoStartup.cs | 15 +++++++-------- .../Flow.Launcher.Infrastructure.csproj | 3 ++- Flow.Launcher/App.xaml.cs | 6 +++--- Flow.Launcher/Flow.Launcher.csproj | 1 - .../ViewModels/SettingsPaneGeneralViewModel.cs | 2 +- 5 files changed, 13 insertions(+), 14 deletions(-) rename {Flow.Launcher/Helper => Flow.Launcher.Infrastructure}/AutoStartup.cs (95%) diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher.Infrastructure/AutoStartup.cs similarity index 95% rename from Flow.Launcher/Helper/AutoStartup.cs rename to Flow.Launcher.Infrastructure/AutoStartup.cs index c5e20504b7d..42797237eb7 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher.Infrastructure/AutoStartup.cs @@ -2,12 +2,11 @@ using System.IO; using System.Linq; using System.Security.Principal; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Microsoft.Win32; using Microsoft.Win32.TaskScheduler; -namespace Flow.Launcher.Helper; +namespace Flow.Launcher.Infrastructure; public class AutoStartup { @@ -32,7 +31,7 @@ public static bool IsEnabled var path = key?.GetValue(Constant.FlowLauncher) as string; return path == Constant.ExecutablePath; } - catch (Exception e) + catch (System.Exception e) { Log.Error("AutoStartup", $"Ignoring non-critical registry error (querying if enabled): {e}"); } @@ -59,7 +58,7 @@ private static bool CheckLogonTask() return true; } - catch (Exception e) + catch (System.Exception e) { Log.Error("AutoStartup", $"Failed to check logon task: {e}"); } @@ -110,7 +109,7 @@ private static void Disable(bool logonTask) key?.DeleteValue(Constant.FlowLauncher, false); } } - catch (Exception e) + catch (System.Exception e) { Log.Error("AutoStartup", $"Failed to disable auto-startup: {e}"); throw; @@ -131,7 +130,7 @@ private static void Enable(bool logonTask) key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\""); } } - catch (Exception e) + catch (System.Exception e) { Log.Error("AutoStartup", $"Failed to enable auto-startup: {e}"); throw; @@ -159,7 +158,7 @@ private static bool ScheduleLogonTask() TaskService.Instance.RootFolder.RegisterTaskDefinition(LogonTaskName, td); return true; } - catch (Exception e) + catch (System.Exception e) { Log.Error("AutoStartup", $"Failed to schedule logon task: {e}"); return false; @@ -174,7 +173,7 @@ private static bool UnscheduleLogonTask() taskService.RootFolder.DeleteTask(LogonTaskName); return true; } - catch (Exception e) + catch (System.Exception e) { Log.Error("AutoStartup", $"Failed to unschedule logon task: {e}"); return false; diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 5d8b264251a..645edfcf0a8 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -1,4 +1,4 @@ - + net7.0-windows @@ -68,6 +68,7 @@ + diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 54710ec425d..1d871aecd12 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -165,17 +165,17 @@ private void AutoStartup() { // we try to enable auto-startup on first launch, or reenable if it was removed // but the user still has the setting set - if (_settings.StartFlowLauncherOnSystemStartup && !Helper.AutoStartup.IsEnabled) + if (_settings.StartFlowLauncherOnSystemStartup && !Infrastructure.AutoStartup.IsEnabled) { try { if (_settings.UseLogonTaskForStartup) { - Helper.AutoStartup.EnableViaLogonTask(); + Infrastructure.AutoStartup.EnableViaLogonTask(); } else { - Helper.AutoStartup.EnableViaRegistry(); + Infrastructure.AutoStartup.EnableViaRegistry(); } } catch (Exception e) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 0baa1bef503..f8ace91f871 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -104,7 +104,6 @@ - diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index dddaa99d46e..894906cd501 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -6,7 +6,7 @@ using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Core.Resource; -using Flow.Launcher.Helper; +using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels;