Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Logon Task for Faster Startup Experience #3218

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Flow.Launcher.Infrastructure/UserSettings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Flow.Launcher/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private void AutoStartup()
{
try
{
Helper.AutoStartup.Enable();
Helper.AutoStartup.Enable(_settings.UseLogonTaskForStartup);
}
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 @@ -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>

Expand Down
115 changes: 109 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,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;
}
Jack251970 marked this conversation as resolved.
Show resolved Hide resolved

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)
{
Expand All @@ -42,17 +88,74 @@ 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)
{
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)
{
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);
}
}
1 change: 1 addition & 0 deletions Flow.Launcher/Languages/en.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<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="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
8 changes: 6 additions & 2 deletions Flow.Launcher/Languages/zh-cn.xaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?xml version="1.0"?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
<?xml version="1.0" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!-- Startup -->
<system:String x:Key="runtimePluginInstalledChooseRuntimePrompt">
Flow 检测到您已安装 {0} 个插件,需要 {1} 才能运行。是否要下载 {1}?
Expand Down Expand Up @@ -44,6 +47,7 @@
<system:String x:Key="portableMode">便携模式</system:String>
<system:String x:Key="portableModeToolTIp">将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。</system:String>
<system:String x:Key="startFlowLauncherOnSystemStartup">开机自启</system:String>
<system:String x:Key="useLogonTaskForStartup">使用登录任务而非启动项以更快自启</system:String>
<system:String x:Key="setAutoStartFailed">设置开机自启时出错</system:String>
<system:String x:Key="hideFlowLauncherWhenLoseFocus">失去焦点时自动隐藏 Flow Launcher</system:String>
<system:String x:Key="dontPromptUpdateMsg">不显示新版本提示</system:String>
Expand Down
8 changes: 6 additions & 2 deletions Flow.Launcher/Languages/zh-tw.xaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?xml version="1.0"?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
<?xml version="1.0" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!-- Startup -->
<system:String x:Key="runtimePluginInstalledChooseRuntimePrompt">
Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}?
Expand Down Expand Up @@ -44,6 +47,7 @@
<system:String x:Key="portableMode">便攜模式</system:String>
<system:String x:Key="portableModeToolTIp">將所有設定和使用者資料存儲在一個資料夾中(當與可移動磁碟或雲服務一起使用時很有用)。</system:String>
<system:String x:Key="startFlowLauncherOnSystemStartup">開機時啟動</system:String>
<system:String x:Key="useLogonTaskForStartup">使用登錄任務而非啟動項以更快自啟</system:String>
<system:String x:Key="setAutoStartFailed">Error setting launch on startup</system:String>
<system:String x:Key="hideFlowLauncherWhenLoseFocus">失去焦點時自動隱藏 Flow Launcher</system:String>
<system:String x:Key="dontPromptUpdateMsg">不顯示新版本提示</system:String>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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<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}">
<ui:ToggleSwitch
IsOn="{Binding UseLogonTaskForStartup}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" />
</cc:Card>

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