mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Add support for changing startup to logon task for faster startup experience
This commit is contained in:
parent
6cf7674cac
commit
3260faba98
6 changed files with 151 additions and 9 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ namespace Flow.Launcher
|
|||
{
|
||||
try
|
||||
{
|
||||
Helper.AutoStartup.Enable();
|
||||
Helper.AutoStartup.Enable(_settings.UseLogonTaskForStartup);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -100,6 +100,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.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SearchWindowScreenData> SearchWindowScreens { get; } =
|
||||
DropdownDataGeneric<SearchWindowScreens>.GetValues<SearchWindowScreenData>("SearchWindowScreen");
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@
|
|||
OnContent="{DynamicResource enable}" />
|
||||
</cc:Card>
|
||||
|
||||
<cc:Card Title="Use logon task instead of startup entry for faster startup experience" Icon="">
|
||||
<ui:ToggleSwitch
|
||||
IsOn="{Binding UseLogonTaskForStartup}"
|
||||
OffContent="{DynamicResource disable}"
|
||||
OnContent="{DynamicResource enable}" />
|
||||
</cc:Card>
|
||||
|
||||
<cc:Card
|
||||
Title="{DynamicResource hideOnStartup}"
|
||||
Icon=""
|
||||
|
|
|
|||
Loading…
Reference in a new issue