diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index c412fb32f..81895fdcc 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -238,6 +238,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
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 4d1adc6cd..38f846d92 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -119,7 +119,7 @@ namespace Flow.Launcher
{
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 788beddfb..570785be7 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 4bff30caf..116520ecf 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 class AutoStartup
}
}
- 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 class AutoStartup
}
}
- 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 @@ public class AutoStartup
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 3d94355e6..0aca761a0 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -42,9 +42,16 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
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 partial class SettingsPaneGeneralViewModel : BaseModel
}
}
+ 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 30e065b16..f57eba654 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -36,6 +36,13 @@
OnContent="{DynamicResource enable}" />
+
+
+
+