122 lines
4.7 KiB
C#
122 lines
4.7 KiB
C#
using Microsoft.Win32;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security.Principal;
|
|
using System.Threading;
|
|
|
|
namespace Bedtimer
|
|
{
|
|
public sealed class Config
|
|
{
|
|
public int BedMinutes { get; set; } = 22 * 60 + 30; // 10:30 PM
|
|
public int WarnLead { get; set; } = 60;
|
|
public int FlashLead { get; set; } = 20;
|
|
public int LockDelay { get; set; } = 5;
|
|
|
|
private const string RegPath = @"SOFTWARE\Whitlocktech\Bedtimer";
|
|
|
|
// --- Public API -------------------------------------------------------
|
|
|
|
public static Config LoadOrCreate()
|
|
{
|
|
// Read only; do NOT write defaults here.
|
|
using var k = OpenHKLM().OpenSubKey(RegPath, writable: false);
|
|
if (k == null) return new Config(); // defaults in memory only
|
|
|
|
int Get(string n, int d) => (k.GetValue(n) is int v) ? v : d;
|
|
|
|
return new Config
|
|
{
|
|
BedMinutes = Get(nameof(BedMinutes), 22 * 60 + 30),
|
|
WarnLead = Get(nameof(WarnLead), 60),
|
|
FlashLead = Get(nameof(FlashLead), 20),
|
|
LockDelay = Get(nameof(LockDelay), 5),
|
|
};
|
|
}
|
|
|
|
public void Save()
|
|
{
|
|
try
|
|
{
|
|
using var root = OpenHKLM();
|
|
using var k = root.CreateSubKey(RegPath, writable: true);
|
|
k.SetValue(nameof(BedMinutes), BedMinutes, RegistryValueKind.DWord);
|
|
k.SetValue(nameof(WarnLead), WarnLead, RegistryValueKind.DWord);
|
|
k.SetValue(nameof(FlashLead), FlashLead, RegistryValueKind.DWord);
|
|
k.SetValue(nameof(LockDelay), LockDelay, RegistryValueKind.DWord);
|
|
Signals.RaiseConfigChanged();
|
|
}
|
|
catch (UnauthorizedAccessException)
|
|
{
|
|
// Relaunch self elevated to write HKLM in the SAME registry view
|
|
var exe = Environment.ProcessPath!;
|
|
var args = $"--save-admin {BedMinutes} {WarnLead} {FlashLead} {LockDelay}";
|
|
Process.Start(new ProcessStartInfo(exe, args)
|
|
{
|
|
UseShellExecute = true,
|
|
Verb = "runas"
|
|
});
|
|
}
|
|
}
|
|
|
|
public static void SaveFromArgs(string[] args)
|
|
{
|
|
// Accept: Bedtimer.exe --save-admin <bed> <warn> <flash> <delay>
|
|
// Find the flag and read the 4 numbers after it.
|
|
int i = Array.FindIndex(args, a => string.Equals(a, "--save-admin", StringComparison.OrdinalIgnoreCase));
|
|
if (i < 0 || args.Length < i + 5) return;
|
|
|
|
var cfg = new Config
|
|
{
|
|
BedMinutes = int.Parse(args[i + 1]),
|
|
WarnLead = int.Parse(args[i + 2]),
|
|
FlashLead = int.Parse(args[i + 3]),
|
|
LockDelay = int.Parse(args[i + 4]),
|
|
};
|
|
|
|
using var root = OpenHKLM();
|
|
using var k = root.CreateSubKey(RegPath, writable: true);
|
|
k.SetValue(nameof(BedMinutes), cfg.BedMinutes, RegistryValueKind.DWord);
|
|
k.SetValue(nameof(WarnLead), cfg.WarnLead, RegistryValueKind.DWord);
|
|
k.SetValue(nameof(FlashLead), cfg.FlashLead, RegistryValueKind.DWord);
|
|
k.SetValue(nameof(LockDelay), cfg.LockDelay, RegistryValueKind.DWord);
|
|
Signals.RaiseConfigChanged();
|
|
}
|
|
|
|
|
|
// Keep %AppData% for state/logs
|
|
public static string Dir => System.IO.Path.Combine(
|
|
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
"Whitlocktech", "Bedtimer");
|
|
|
|
// --- Helpers ----------------------------------------------------------
|
|
|
|
private static RegistryKey OpenHKLM()
|
|
{
|
|
// Always open the correct view explicitly to avoid WOW6432 redirection issues
|
|
var view = Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32;
|
|
return RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view);
|
|
}
|
|
|
|
public static bool IsProcessElevated()
|
|
{
|
|
using var id = WindowsIdentity.GetCurrent();
|
|
var p = new WindowsPrincipal(id);
|
|
return p.IsInRole(WindowsBuiltInRole.Administrator);
|
|
}
|
|
}
|
|
|
|
public static class Signals
|
|
{
|
|
public const string ConfigChangedName = @"Local\Bedtimer_Config_Changed";
|
|
public static void RaiseConfigChanged()
|
|
{
|
|
using var ev = new EventWaitHandle(false, EventResetMode.AutoReset, ConfigChangedName);
|
|
ev.Set();
|
|
}
|
|
public static EventWaitHandle SubscribeConfigChanged()
|
|
=> new EventWaitHandle(false, EventResetMode.AutoReset, ConfigChangedName);
|
|
}
|
|
}
|