-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStartupManager.cs
More file actions
102 lines (93 loc) · 3.3 KB
/
StartupManager.cs
File metadata and controls
102 lines (93 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using System.Runtime.InteropServices;
namespace CapsNumTray;
/// <summary>
/// Manages .lnk shortcut in the user's Startup folder.
/// Uses WScript.Shell COM for shortcut creation.
/// </summary>
internal static class StartupManager
{
private static string ShortcutPath =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), "CapsNumTray.lnk");
public static bool IsEnabled => File.Exists(ShortcutPath);
public static void Toggle()
{
if (IsEnabled)
{
try { File.Delete(ShortcutPath); } catch { }
}
else
{
CreateShortcut();
}
}
public static void SetEnabled(bool enabled)
{
if (enabled == IsEnabled) return;
Toggle();
}
/// <summary>
/// Self-heal startup shortcut if the exe has moved (e.g., winget upgrade to a new version folder).
/// Best-effort — silently ignored if COM is unavailable or shortcut doesn't exist.
/// </summary>
public static void ValidateStartupPath()
{
if (!File.Exists(ShortcutPath)) return;
try
{
var shellType = Type.GetTypeFromProgID("WScript.Shell");
if (shellType == null) return;
dynamic shell = Activator.CreateInstance(shellType)!;
try
{
dynamic shortcut = shell.CreateShortcut(ShortcutPath);
try
{
var targetPath = (string)shortcut.TargetPath;
var currentPath = Environment.ProcessPath ?? "";
if (!targetPath.Equals(currentPath, StringComparison.OrdinalIgnoreCase))
{
shortcut.TargetPath = currentPath;
shortcut.WorkingDirectory = Path.GetDirectoryName(currentPath) ?? "";
shortcut.Save();
}
}
finally { Marshal.FinalReleaseComObject(shortcut); }
}
finally { Marshal.FinalReleaseComObject(shell); }
}
catch { /* Best-effort */ }
}
private static void CreateShortcut()
{
object? shell = null;
object? shortcut = null;
try
{
var shellType = Type.GetTypeFromProgID("WScript.Shell");
if (shellType == null) return;
shell = Activator.CreateInstance(shellType);
if (shell == null) return;
dynamic dynShell = shell;
shortcut = dynShell.CreateShortcut(ShortcutPath);
dynamic sc = shortcut;
sc.TargetPath = Environment.ProcessPath;
sc.WorkingDirectory = Path.GetDirectoryName(Environment.ProcessPath) ?? "";
sc.Save();
}
catch (Exception ex)
{
// Folder Redirection GPO can make the Startup folder read-only
// (or invisible). Log so DebugView users can diagnose why their
// "Run at startup" setting didn't take.
System.Diagnostics.Trace.WriteLine(
$"CapsNumTray: CreateShortcut failed ({ex.GetType().Name}: {ex.Message})");
}
finally
{
if (shortcut != null)
Marshal.ReleaseComObject(shortcut);
if (shell != null)
Marshal.ReleaseComObject(shell);
}
}
}