Skip to content

Commit

Permalink
Merge pull request #3218 from Jack251970/logon_task
Browse files Browse the repository at this point in the history
Support Logon Task for Faster Startup Experience
  • Loading branch information
jjw24 authored Feb 25, 2025
2 parents 9aadc3a + fe48427 commit c143aa4
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 9 deletions.
1 change: 1 addition & 0 deletions Flow.Launcher.Infrastructure/UserSettings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,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
Expand Down
9 changes: 8 additions & 1 deletion Flow.Launcher/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,14 @@ private void AutoStartup()
{
try
{
Helper.AutoStartup.Enable();
if (_settings.UseLogonTaskForStartup)
{
Helper.AutoStartup.EnableViaLogonTask();
}
else
{
Helper.AutoStartup.EnableViaRegistry();
}
}
catch (Exception e)
{
Expand Down
1 change: 1 addition & 0 deletions Flow.Launcher/Flow.Launcher.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
<PackageReference Include="TaskScheduler" Version="2.11.0" />
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.1" />
</ItemGroup>

Expand Down
144 changes: 138 additions & 6 deletions Flow.Launcher/Helper/AutoStartup.cs
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -28,12 +41,74 @@ 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();
}

return true;
}
catch (Exception e)
{
Log.Error("AutoStartup", $"Failed to check logon task: {e}");
}
}

return false;
}

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
{
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)
{
Expand All @@ -42,17 +117,74 @@ public static void Disable()
}
}

internal static void Enable()
private 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)
{
Log.Error("AutoStartup", $"Failed to enable auto-startup: {e}");
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 e)
{
Log.Error("AutoStartup", $"Failed to schedule logon task: {e}");
return false;
}
}

private static bool UnscheduleLogonTask()
{
using var taskService = new TaskService();
try
{
taskService.RootFolder.DeleteTask(LogonTaskName);
return true;
}
catch (Exception e)
{
Log.Error("AutoStartup", $"Failed to unschedule logon task: {e}");
return false;
}
}

private static bool IsCurrentUserIsAdmin()
{
var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
2 changes: 2 additions & 0 deletions Flow.Launcher/Languages/en.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
<system:String x:Key="portableMode">Portable Mode</system:String>
<system:String x:Key="portableModeToolTIp">Store all settings and user data in one folder (Useful when used with removable drives or cloud services).</system:String>
<system:String x:Key="startFlowLauncherOnSystemStartup">Start Flow Launcher on system startup</system:String>
<system:String x:Key="useLogonTaskForStartup">Use logon task instead of startup entry for faster startup experience</system:String>
<system:String x:Key="useLogonTaskForStartupTooltip">After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler</system:String>
<system:String x:Key="setAutoStartFailed">Error setting launch on startup</system:String>
<system:String x:Key="hideFlowLauncherWhenLoseFocus">Hide Flow Launcher when focus is lost</system:String>
<system:String x:Key="dontPromptUpdateMsg">Do not show new version notifications</system:String>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,20 @@ public bool StartFlowLauncherOnSystemStartup
try
{
if (value)
AutoStartup.Enable();
{
if (UseLogonTaskForStartup)
{
AutoStartup.EnableViaLogonTask();
}
else
{
AutoStartup.EnableViaRegistry();
}
}
else
AutoStartup.Disable();
{
AutoStartup.DisableViaLogonTaskAndRegistry();
}
}
catch (Exception e)
{
Expand All @@ -54,6 +65,34 @@ public bool StartFlowLauncherOnSystemStartup
}
}

public bool UseLogonTaskForStartup
{
get => Settings.UseLogonTaskForStartup;
set
{
Settings.UseLogonTaskForStartup = value;

if (StartFlowLauncherOnSystemStartup)
{
try
{
if (UseLogonTaskForStartup)
{
AutoStartup.ChangeToViaLogonTask();
}
else
{
AutoStartup.ChangeToViaRegistry();
}
}
catch (Exception e)
{
Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"),
e.Message);
}
}
}
}

public List<SearchWindowScreenData> SearchWindowScreens { get; } =
DropdownDataGeneric<SearchWindowScreens>.GetValues<SearchWindowScreenData>("SearchWindowScreen");
Expand Down
7 changes: 7 additions & 0 deletions Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
OnContent="{DynamicResource enable}" />
</cc:Card>

<cc:Card Title="{DynamicResource useLogonTaskForStartup}" Sub="{DynamicResource useLogonTaskForStartupTooltip}">
<ui:ToggleSwitch
IsOn="{Binding UseLogonTaskForStartup}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" />
</cc:Card>

<cc:Card
Title="{DynamicResource hideOnStartup}"
Icon="&#xed1a;"
Expand Down

0 comments on commit c143aa4

Please sign in to comment.