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 EnableUpdateLog { get; set; }
|
||||||
|
|
||||||
public bool StartFlowLauncherOnSystemStartup { get; set; } = false;
|
public bool StartFlowLauncherOnSystemStartup { get; set; } = false;
|
||||||
|
public bool UseLogonTaskForStartup { get; set; } = false;
|
||||||
public bool HideOnStartup { get; set; } = true;
|
public bool HideOnStartup { get; set; } = true;
|
||||||
bool _hideNotifyIcon { get; set; }
|
bool _hideNotifyIcon { get; set; }
|
||||||
public bool HideNotifyIcon
|
public bool HideNotifyIcon
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ namespace Flow.Launcher
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Helper.AutoStartup.Enable();
|
Helper.AutoStartup.Enable(_settings.UseLogonTaskForStartup);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@
|
||||||
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
|
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
|
||||||
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
|
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
|
||||||
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
|
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
|
||||||
|
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
||||||
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />
|
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,31 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Principal;
|
||||||
using Flow.Launcher.Infrastructure;
|
using Flow.Launcher.Infrastructure;
|
||||||
using Flow.Launcher.Infrastructure.Logger;
|
using Flow.Launcher.Infrastructure.Logger;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
using Microsoft.Win32.TaskScheduler;
|
||||||
|
|
||||||
namespace Flow.Launcher.Helper;
|
namespace Flow.Launcher.Helper;
|
||||||
|
|
||||||
public class AutoStartup
|
public class AutoStartup
|
||||||
{
|
{
|
||||||
private const string StartupPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
|
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
|
public static bool IsEnabled
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// Check if logon task is enabled
|
||||||
|
if (CheckLogonTask())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if registry is enabled
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
|
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
|
try
|
||||||
{
|
{
|
||||||
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
|
if (logonTask)
|
||||||
key?.DeleteValue(Constant.FlowLauncher, false);
|
{
|
||||||
|
UnscheduleLogonTask();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
|
||||||
|
key?.DeleteValue(Constant.FlowLauncher, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -42,12 +88,19 @@ public class AutoStartup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Enable()
|
internal static void Enable(bool logonTask)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
|
if (logonTask)
|
||||||
key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\"");
|
{
|
||||||
|
ScheduleLogonTask();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
|
||||||
|
key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\"");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
@ -55,4 +108,54 @@ public class AutoStartup
|
||||||
throw;
|
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
|
try
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
AutoStartup.Enable();
|
{
|
||||||
|
// Enable either registry or task scheduler
|
||||||
|
AutoStartup.Enable(UseLogonTaskForStartup);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
AutoStartup.Disable();
|
{
|
||||||
|
// Disable both registry and task scheduler
|
||||||
|
AutoStartup.Disable(true);
|
||||||
|
AutoStartup.Disable(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
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; } =
|
public List<SearchWindowScreenData> SearchWindowScreens { get; } =
|
||||||
DropdownDataGeneric<SearchWindowScreens>.GetValues<SearchWindowScreenData>("SearchWindowScreen");
|
DropdownDataGeneric<SearchWindowScreens>.GetValues<SearchWindowScreenData>("SearchWindowScreen");
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,13 @@
|
||||||
OnContent="{DynamicResource enable}" />
|
OnContent="{DynamicResource enable}" />
|
||||||
</cc:Card>
|
</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
|
<cc:Card
|
||||||
Title="{DynamicResource hideOnStartup}"
|
Title="{DynamicResource hideOnStartup}"
|
||||||
Icon=""
|
Icon=""
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue