|
|
@@ -0,0 +1,202 @@
|
|
|
+using System.Runtime.InteropServices;
|
|
|
+using Microsoft.Win32;
|
|
|
+using Serilog;
|
|
|
+
|
|
|
+namespace YZWater.Core.Services;
|
|
|
+
|
|
|
+/// <summary>
|
|
|
+/// 跨平台开机自启动管理服务
|
|
|
+/// </summary>
|
|
|
+public static class StartupService
|
|
|
+{
|
|
|
+ private const string AppName = "YZWater";
|
|
|
+ private const string WindowsRegistryPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
|
|
+ private const string LinuxDesktopFileName = "yzwater.desktop";
|
|
|
+ private const string MacPlistFileName = "com.yxwater.yzwater.plist";
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 设置开机自启动
|
|
|
+ /// </summary>
|
|
|
+ public static bool SetAutoStart(bool enabled)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
+ return SetWindowsAutoStart(enabled);
|
|
|
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
+ return SetLinuxAutoStart(enabled);
|
|
|
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
|
|
+ return SetMacAutoStart(enabled);
|
|
|
+
|
|
|
+ Log.Warning("StartupService: 不支持的操作系统");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Log.Error(ex, "StartupService: 设置开机自启动失败 (enabled={Enabled})", enabled);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 检查是否已启用开机自启动
|
|
|
+ /// </summary>
|
|
|
+ public static bool IsAutoStartEnabled()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
+ return IsWindowsAutoStartEnabled();
|
|
|
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
|
+ return IsLinuxAutoStartEnabled();
|
|
|
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
|
|
+ return IsMacAutoStartEnabled();
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Log.Error(ex, "StartupService: 检查开机自启动状态失败");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取当前可执行文件路径
|
|
|
+ /// </summary>
|
|
|
+ private static string GetExecutablePath()
|
|
|
+ {
|
|
|
+ return Environment.ProcessPath ?? Environment.GetCommandLineArgs()[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ #region Windows
|
|
|
+
|
|
|
+ private static bool SetWindowsAutoStart(bool enabled)
|
|
|
+ {
|
|
|
+ using var key = Registry.CurrentUser.OpenSubKey(WindowsRegistryPath, true);
|
|
|
+ if (key == null)
|
|
|
+ {
|
|
|
+ Log.Error("StartupService: 无法打开注册表路径 {Path}", WindowsRegistryPath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (enabled)
|
|
|
+ {
|
|
|
+ key.SetValue(AppName, GetExecutablePath());
|
|
|
+ Log.Information("StartupService: Windows 开机自启动已启用");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ key.DeleteValue(AppName, false);
|
|
|
+ Log.Information("StartupService: Windows 开机自启动已禁用");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool IsWindowsAutoStartEnabled()
|
|
|
+ {
|
|
|
+ using var key = Registry.CurrentUser.OpenSubKey(WindowsRegistryPath);
|
|
|
+ return key?.GetValue(AppName) != null;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region Linux
|
|
|
+
|
|
|
+ private static string GetLinuxDesktopFilePath()
|
|
|
+ {
|
|
|
+ var configDir = Path.Combine(
|
|
|
+ Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
|
|
+ ".config", "autostart");
|
|
|
+ return Path.Combine(configDir, LinuxDesktopFileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool SetLinuxAutoStart(bool enabled)
|
|
|
+ {
|
|
|
+ var filePath = GetLinuxDesktopFilePath();
|
|
|
+
|
|
|
+ if (enabled)
|
|
|
+ {
|
|
|
+ var dir = Path.GetDirectoryName(filePath)!;
|
|
|
+ Directory.CreateDirectory(dir);
|
|
|
+
|
|
|
+ var content = $"""
|
|
|
+ [Desktop Entry]
|
|
|
+ Type=Application
|
|
|
+ Name={AppName}
|
|
|
+ Exec={GetExecutablePath()}
|
|
|
+ X-GNOME-Autostart-enabled=true
|
|
|
+ """;
|
|
|
+ File.WriteAllText(filePath, content);
|
|
|
+ Log.Information("StartupService: Linux 开机自启动已启用 ({Path})", filePath);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (File.Exists(filePath))
|
|
|
+ File.Delete(filePath);
|
|
|
+ Log.Information("StartupService: Linux 开机自启动已禁用");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool IsLinuxAutoStartEnabled()
|
|
|
+ {
|
|
|
+ return File.Exists(GetLinuxDesktopFilePath());
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region macOS
|
|
|
+
|
|
|
+ private static string GetMacPlistPath()
|
|
|
+ {
|
|
|
+ var libraryDir = Path.Combine(
|
|
|
+ Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
|
|
+ "Library", "LaunchAgents");
|
|
|
+ return Path.Combine(libraryDir, MacPlistFileName);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool SetMacAutoStart(bool enabled)
|
|
|
+ {
|
|
|
+ var filePath = GetMacPlistPath();
|
|
|
+
|
|
|
+ if (enabled)
|
|
|
+ {
|
|
|
+ var dir = Path.GetDirectoryName(filePath)!;
|
|
|
+ Directory.CreateDirectory(dir);
|
|
|
+
|
|
|
+ var content = $"""
|
|
|
+ <?xml version="1.0" encoding="UTF-8"?>
|
|
|
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
|
+ <plist version="1.0">
|
|
|
+ <dict>
|
|
|
+ <key>Label</key>
|
|
|
+ <string>com.yxwater.yzwater</string>
|
|
|
+ <key>ProgramArguments</key>
|
|
|
+ <array>
|
|
|
+ <string>{GetExecutablePath()}</string>
|
|
|
+ </array>
|
|
|
+ <key>RunAtLoad</key>
|
|
|
+ <true/>
|
|
|
+ </dict>
|
|
|
+ </plist>
|
|
|
+ """;
|
|
|
+ File.WriteAllText(filePath, content);
|
|
|
+ Log.Information("StartupService: macOS 开机自启动已启用 ({Path})", filePath);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (File.Exists(filePath))
|
|
|
+ File.Delete(filePath);
|
|
|
+ Log.Information("StartupService: macOS 开机自启动已禁用");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static bool IsMacAutoStartEnabled()
|
|
|
+ {
|
|
|
+ return File.Exists(GetMacPlistPath());
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+}
|