From 3260faba985a595b2df48c0541ebb9bef6aea88e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 31 Jan 2025 22:01:29 +0800 Subject: [PATCH 1/7] Add support for changing startup to logon task for faster startup experience --- .../UserSettings/Settings.cs | 1 + Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/Flow.Launcher.csproj | 1 + Flow.Launcher/Helper/AutoStartup.cs | 115 +++++++++++++++++- .../SettingsPaneGeneralViewModel.cs | 34 +++++- .../Views/SettingsPaneGeneral.xaml | 7 ++ 6 files changed, 151 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index c412fb32f5a..81895fdcc3c 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -238,6 +238,7 @@ public SearchPrecisionScore QuerySearchPrecision public bool EnableUpdateLog { get; set; } public bool StartFlowLauncherOnSystemStartup { get; set; } = false; + public bool UseLogonTaskForStartup { get; set; } = false; public bool HideOnStartup { get; set; } = true; bool _hideNotifyIcon { get; set; } public bool HideNotifyIcon diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 4d1adc6cd51..38f846d92e9 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -119,7 +119,7 @@ private void AutoStartup() { try { - Helper.AutoStartup.Enable(); + Helper.AutoStartup.Enable(_settings.UseLogonTaskForStartup); } catch (Exception e) { diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 788beddfb37..570785be709 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -100,6 +100,7 @@ + diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 4bff30caf03..116520ecfb3 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -1,18 +1,31 @@ using System; +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; public class AutoStartup { private const string StartupPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; + private const string LogonTaskName = $"{Constant.FlowLauncher} Startup"; + private const string LogonTaskDesc = $"{Constant.FlowLauncher} Auto Startup"; public static bool IsEnabled { get { + // Check if logon task is enabled + if (CheckLogonTask()) + { + return true; + } + + // Check if registry is enabled try { using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); @@ -28,12 +41,45 @@ public static bool IsEnabled } } - public static void Disable() + private static bool CheckLogonTask() + { + using var taskService = new TaskService(); + var task = taskService.RootFolder.AllTasks.FirstOrDefault(t => t.Name == LogonTaskName); + if (task != null) + { + try + { + // Check if the action is the same as the current executable path + var action = task.Definition.Actions.FirstOrDefault()!.ToString().Trim(); + if (!Constant.ExecutablePath.Equals(action, StringComparison.OrdinalIgnoreCase) && !File.Exists(action)) + { + UnscheduleLogonTask(); + ScheduleLogonTask(); + } + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to check logon task"); + return false; + } + } + + return true; + } + + public static void Disable(bool logonTask) { try { - using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); - key?.DeleteValue(Constant.FlowLauncher, false); + if (logonTask) + { + UnscheduleLogonTask(); + } + else + { + using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); + key?.DeleteValue(Constant.FlowLauncher, false); + } } catch (Exception e) { @@ -42,12 +88,19 @@ public static void Disable() } } - internal static void Enable() + internal static void Enable(bool logonTask) { try { - using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); - key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\""); + if (logonTask) + { + ScheduleLogonTask(); + } + else + { + using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); + key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\""); + } } catch (Exception e) { @@ -55,4 +108,54 @@ internal static void Enable() throw; } } + + private static bool ScheduleLogonTask() + { + using var td = TaskService.Instance.NewTask(); + td.RegistrationInfo.Description = LogonTaskDesc; + td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name, Delay = TimeSpan.FromSeconds(2) }); + td.Actions.Add(Constant.ExecutablePath); + + if (IsCurrentUserIsAdmin()) + { + td.Principal.RunLevel = TaskRunLevel.Highest; + } + + td.Settings.StopIfGoingOnBatteries = false; + td.Settings.DisallowStartIfOnBatteries = false; + td.Settings.ExecutionTimeLimit = TimeSpan.Zero; + + try + { + TaskService.Instance.RootFolder.RegisterTaskDefinition(LogonTaskName, td); + return true; + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to schedule logon task"); + return false; + } + } + + private static bool UnscheduleLogonTask() + { + using var taskService = new TaskService(); + try + { + taskService.RootFolder.DeleteTask(LogonTaskName); + return true; + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to unschedule logon task"); + return false; + } + } + + private static bool IsCurrentUserIsAdmin() + { + var identity = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 3d94355e687..0aca761a0fe 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -42,9 +42,16 @@ public bool StartFlowLauncherOnSystemStartup try { if (value) - AutoStartup.Enable(); + { + // Enable either registry or task scheduler + AutoStartup.Enable(UseLogonTaskForStartup); + } else - AutoStartup.Disable(); + { + // Disable both registry and task scheduler + AutoStartup.Disable(true); + AutoStartup.Disable(false); + } } catch (Exception e) { @@ -54,6 +61,29 @@ public bool StartFlowLauncherOnSystemStartup } } + public bool UseLogonTaskForStartup + { + get => Settings.UseLogonTaskForStartup; + set + { + Settings.UseLogonTaskForStartup = value; + + if (StartFlowLauncherOnSystemStartup) + { + try + { + // Disable and enable to update the startup method + AutoStartup.Disable(!UseLogonTaskForStartup); + AutoStartup.Enable(UseLogonTaskForStartup); + } + catch (Exception e) + { + Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"), + e.Message); + } + } + } + } public List SearchWindowScreens { get; } = DropdownDataGeneric.GetValues("SearchWindowScreen"); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 30e065b1601..f57eba65416 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,6 +36,13 @@ OnContent="{DynamicResource enable}" /> + + + + Date: Fri, 31 Jan 2025 22:06:53 +0800 Subject: [PATCH 2/7] Move string to resources --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/Languages/zh-cn.xaml | 8 ++++++-- Flow.Launcher/Languages/zh-tw.xaml | 8 ++++++-- Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4c465d61f52..8e8c9abefe6 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -46,6 +46,7 @@ Portable Mode Store all settings and user data in one folder (Useful when used with removable drives or cloud services). Start Flow Launcher on system startup + Use logon task instead of startup entry for faster startup experience Error setting launch on startup Hide Flow Launcher when focus is lost Do not show new version notifications diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index 681c715fb03..d2d1044af7e 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -1,5 +1,8 @@ - - + + Flow 检测到您已安装 {0} 个插件,需要 {1} 才能运行。是否要下载 {1}? @@ -44,6 +47,7 @@ 便携模式 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 开机自启 + 使用登录任务而非启动项以更快自启 设置开机自启时出错 失去焦点时自动隐藏 Flow Launcher 不显示新版本提示 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 44be5257bb2..b5aa5337781 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -1,5 +1,8 @@ - - + + Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? @@ -44,6 +47,7 @@ 便攜模式 將所有設定和使用者資料存儲在一個資料夾中(當與可移動磁碟或雲服務一起使用時很有用)。 開機時啟動 + 使用登錄任務而非啟動項以更快自啟 Error setting launch on startup 失去焦點時自動隱藏 Flow Launcher 不顯示新版本提示 diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index f57eba65416..e52614e7478 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,7 +36,7 @@ OnContent="{DynamicResource enable}" /> - + Date: Fri, 31 Jan 2025 22:22:00 +0800 Subject: [PATCH 3/7] Fix issue when checking logon task --- Flow.Launcher/Helper/AutoStartup.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 116520ecfb3..79466f1fb1b 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -56,15 +56,16 @@ private static bool CheckLogonTask() UnscheduleLogonTask(); ScheduleLogonTask(); } + + return true; } catch (Exception) { Log.Error("AutoStartup", "Failed to check logon task"); - return false; } } - return true; + return false; } public static void Disable(bool logonTask) From 1ff8c3620a030294a6d30d9ae2e93ac14438457a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Feb 2025 07:56:24 +0800 Subject: [PATCH 4/7] Revert changes in non-English language files --- Flow.Launcher/Languages/zh-cn.xaml | 8 ++------ Flow.Launcher/Languages/zh-tw.xaml | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index d2d1044af7e..681c715fb03 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -1,8 +1,5 @@ - - + + Flow 检测到您已安装 {0} 个插件,需要 {1} 才能运行。是否要下载 {1}? @@ -47,7 +44,6 @@ 便携模式 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 开机自启 - 使用登录任务而非启动项以更快自启 设置开机自启时出错 失去焦点时自动隐藏 Flow Launcher 不显示新版本提示 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index b5aa5337781..44be5257bb2 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -1,8 +1,5 @@ - - + + Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? @@ -47,7 +44,6 @@ 便攜模式 將所有設定和使用者資料存儲在一個資料夾中(當與可移動磁碟或雲服務一起使用時很有用)。 開機時啟動 - 使用登錄任務而非啟動項以更快自啟 Error setting launch on startup 失去焦點時自動隱藏 Flow Launcher 不顯示新版本提示 From 585b7015b6236ea7fdbe156c39d468a3ca579ed5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 10 Feb 2025 18:20:50 +0800 Subject: [PATCH 5/7] Add uninstallation tooltip for logon task settings item --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 8e8c9abefe6..cd9d0b02adb 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -47,6 +47,7 @@ Store all settings and user data in one folder (Useful when used with removable drives or cloud services). Start Flow Launcher on system startup Use logon task instead of startup entry for faster startup experience + After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler Error setting launch on startup Hide Flow Launcher when focus is lost Do not show new version notifications diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index e52614e7478..a80e618e8b4 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,7 +36,7 @@ OnContent="{DynamicResource enable}" /> - + Date: Mon, 24 Feb 2025 19:55:48 +0800 Subject: [PATCH 6/7] Improve function names for code quality --- Flow.Launcher/App.xaml.cs | 9 +++++- Flow.Launcher/Helper/AutoStartup.cs | 32 +++++++++++++++++-- .../SettingsPaneGeneralViewModel.cs | 25 ++++++++++----- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 38f846d92e9..f74e9a38886 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -119,7 +119,14 @@ private void AutoStartup() { try { - Helper.AutoStartup.Enable(_settings.UseLogonTaskForStartup); + if (_settings.UseLogonTaskForStartup) + { + Helper.AutoStartup.EnableViaLogonTask(); + } + else + { + Helper.AutoStartup.EnableViaRegistry(); + } } catch (Exception e) { diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 79466f1fb1b..936951ee96c 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -68,7 +68,35 @@ private static bool CheckLogonTask() return false; } - public static void Disable(bool logonTask) + public static void DisableViaLogonTaskAndRegistry() + { + Disable(true); + Disable(false); + } + + public static void EnableViaLogonTask() + { + Enable(true); + } + + public static void EnableViaRegistry() + { + Enable(false); + } + + public static void ChangeToViaLogonTask() + { + Disable(false); + Enable(true); + } + + public static void ChangeToViaRegistry() + { + Disable(true); + Enable(false); + } + + private static void Disable(bool logonTask) { try { @@ -89,7 +117,7 @@ public static void Disable(bool logonTask) } } - internal static void Enable(bool logonTask) + private static void Enable(bool logonTask) { try { diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 0aca761a0fe..ab38cd51408 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -43,14 +43,18 @@ public bool StartFlowLauncherOnSystemStartup { if (value) { - // Enable either registry or task scheduler - AutoStartup.Enable(UseLogonTaskForStartup); + if (UseLogonTaskForStartup) + { + AutoStartup.EnableViaLogonTask(); + } + else + { + AutoStartup.EnableViaRegistry(); + } } else { - // Disable both registry and task scheduler - AutoStartup.Disable(true); - AutoStartup.Disable(false); + AutoStartup.DisableViaLogonTaskAndRegistry(); } } catch (Exception e) @@ -72,9 +76,14 @@ public bool UseLogonTaskForStartup { try { - // Disable and enable to update the startup method - AutoStartup.Disable(!UseLogonTaskForStartup); - AutoStartup.Enable(UseLogonTaskForStartup); + if (UseLogonTaskForStartup) + { + AutoStartup.ChangeToViaLogonTask(); + } + else + { + AutoStartup.ChangeToViaRegistry(); + } } catch (Exception e) { From fe48427252f5ce8c84e697da42a24406d9675a3f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 25 Feb 2025 15:08:27 +0800 Subject: [PATCH 7/7] Log error for logon task --- Flow.Launcher/Helper/AutoStartup.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 936951ee96c..c5e20504b7d 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -59,9 +59,9 @@ private static bool CheckLogonTask() return true; } - catch (Exception) + catch (Exception e) { - Log.Error("AutoStartup", "Failed to check logon task"); + Log.Error("AutoStartup", $"Failed to check logon task: {e}"); } } @@ -159,9 +159,9 @@ private static bool ScheduleLogonTask() TaskService.Instance.RootFolder.RegisterTaskDefinition(LogonTaskName, td); return true; } - catch (Exception) + catch (Exception e) { - Log.Error("AutoStartup", "Failed to schedule logon task"); + Log.Error("AutoStartup", $"Failed to schedule logon task: {e}"); return false; } } @@ -174,9 +174,9 @@ private static bool UnscheduleLogonTask() taskService.RootFolder.DeleteTask(LogonTaskName); return true; } - catch (Exception) + catch (Exception e) { - Log.Error("AutoStartup", "Failed to unschedule logon task"); + Log.Error("AutoStartup", $"Failed to unschedule logon task: {e}"); return false; } }