Files
cursor-lang/CursorLang/Services/StartupService.cs
T

86 lines
3.0 KiB
C#

using System.Runtime.InteropServices;
using CursorLang.Interop;
using CursorLang.Models;
using Windows.ApplicationModel;
namespace CursorLang.Services;
/// <summary>
/// Startup, arranged by whatever means the current build has.
/// </summary>
/// <remarks>
/// Startup used to be a scheduled task with the highest rights — otherwise an app
/// that wanted administrator rights would not start from the startup folder. The
/// app needs no such rights any more, and the two ways left are simpler.
///
/// A package declares the task in its manifest, and Windows lists it for the user
/// next to the rest under Settings — Apps — Startup. Turned off there, it can no
/// longer be turned back on by the app. Outside a package the same setting is kept
/// in the registry: see <see cref="RegistryStartup"/>.
/// </remarks>
public sealed class StartupService : IStartupService
{
/// <summary>Matches TaskId in the package manifest.</summary>
private const string TaskId = "CursorLangStartup";
private readonly RegistryStartup _registry = new();
public async Task<StartupState> GetStateAsync()
{
if (!PackageIdentityNative.IsPackaged)
{
return _registry.GetState();
}
try
{
StartupTask task = await StartupTask.GetAsync(TaskId);
return Translate(task.State);
}
catch (Exception e) when (e is COMException or ArgumentException or InvalidOperationException)
{
// No task by that name in the manifest: that happens to a package put
// together by hand. The setting simply will not show
return StartupState.Unavailable;
}
}
public async Task<StartupState> SetEnabledAsync(bool enabled)
{
if (!PackageIdentityNative.IsPackaged)
{
return _registry.SetEnabled(enabled);
}
try
{
StartupTask task = await StartupTask.GetAsync(TaskId);
if (!enabled)
{
task.Disable();
return Translate(task.State);
}
// Windows answers with a state rather than with success: once the user
// has forbidden startup, the ban stays
return Translate(await task.RequestEnableAsync());
}
catch (Exception e) when (e is COMException or ArgumentException or InvalidOperationException)
{
return StartupState.Unavailable;
}
}
/// <summary>The state of a Windows task in the app's own terms.</summary>
internal static StartupState Translate(StartupTaskState state) => state switch
{
StartupTaskState.Enabled => StartupState.Enabled,
StartupTaskState.EnabledByPolicy => StartupState.EnabledByPolicy,
StartupTaskState.Disabled => StartupState.Disabled,
StartupTaskState.DisabledByUser => StartupState.DisabledByUser,
StartupTaskState.DisabledByPolicy => StartupState.DisabledByPolicy,
_ => StartupState.Unavailable,
};
}