| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- using Microsoft.Win32;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace CCDCount.DLL.Tools
- {
- public class AutoStartHelper
- {
- // 注册表路径
- private static readonly string RegistryPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
- // 应用名称,作为注册表键名
- private static readonly string AppName = "CCDCount";
- /// <summary>
- /// 获取当前可执行文件路径(带引号,用于注册表)
- /// </summary>
- public static string GetExecutablePathForRegistry()
- {
- string path = Process.GetCurrentProcess().MainModule.FileName;
- // 如果路径包含空格,必须用双引号包裹
- if (path.Contains(" "))
- {
- return $"\"{path}\"";
- }
- return path;
- }
- /// <summary>
- /// 获取当前可执行文件路径
- /// </summary>
- public static string GetExecutablePath()
- {
- return Process.GetCurrentProcess().MainModule.FileName;
- }
- /// <summary>
- /// 检查是否已设置自启动
- /// </summary>
- public static bool IsAutoStart()
- {
- using (var key = Registry.CurrentUser.OpenSubKey(RegistryPath, false))
- {
- if (key == null) return false;
- var value = key.GetValue(AppName);
- // 验证路径是否一致,防止exe移动后失效
- return value != null && value.ToString() == GetExecutablePath();
- }
- }
- /// <summary>
- /// 设置或取消自启动
- /// </summary>
- /// <param name="isAutoStart">true 为启用,false 为禁用</param>
- public static void SetAutoStart(bool isAutoStart)
- {
- using (var key = Registry.CurrentUser.OpenSubKey(RegistryPath, true))
- {
- if (key == null) return;
- if (isAutoStart)
- {
- if (!IsAutoStart())
- {
- key.SetValue(AppName, GetExecutablePathForRegistry());
- }
- }
- else
- {
- // false 参数表示值不存在时不抛出异常
- key.DeleteValue(AppName, false);
- }
- }
- }
- private const string TaskName = "CCDCount";
- /// <summary>
- /// 检查任务是否已注册且处于启用状态
- /// </summary>
- /// <returns>true: 已注册且启用; false: 未注册或已禁用</returns>
- public static bool IsTaskRegisteredAndEnabled()
- {
- try
- {
- // 查询任务状态
- // /fo LIST 以列表格式输出
- // /v 显示详细信息
- string arguments = $"/query /tn \"{TaskName}\" /fo LIST /v";
- ProcessStartInfo startInfo = new ProcessStartInfo
- {
- FileName = "schtasks",
- Arguments = arguments,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- CreateNoWindow = true
- };
- using (Process process = Process.Start(startInfo))
- {
- string output = process.StandardOutput.ReadToEnd();
- process.WaitForExit();
- if (process.ExitCode == 0)
- {
- // 检查输出中是否包含 "Status: Ready" 或 "State: Enabled"
- // 不同语言版本的Windows输出可能略有不同,通常检查 "Ready" 或 "Enabled"
- // 英文系统: "Status: Ready"
- // 中文系统: "状态: 就绪"
- // 更通用的方法是检查是否存在该任务名,且没有报错
- // 如果需要严格判断是否启用,可以解析输出中的 "Status" 行
- if (output.Contains("Ready") || output.Contains("就绪"))
- {
- return true;
- }
- // 如果任务是 "Disabled" (禁用) 或 "Disabled" (中文: 已禁用),则返回 false
- if (output.Contains("Disabled") || output.Contains("已禁用"))
- {
- return false;
- }
- // 其他状态视为未准备好
- return false;
- }
- else
- {
- // 退出码非0,通常意味着任务不存在 (ERROR: The system cannot find the file specified.)
- return false;
- }
- }
- }
- catch (Exception)
- {
- // 发生异常时,保守地认为未注册,以便后续尝试重新注册
- return false;
- }
- }
- /// <summary>
- /// 创建或更新开机自启任务
- /// </summary>
- public static void RegisterTask()
- {
- // 1. 先检查是否已经正确配置
- if (IsTaskRegisteredAndEnabled())
- {
- // 可选:进一步检查路径是否一致,如果路径变了也需要更新
- // 这里为了简化,如果已启用则直接返回,避免重复弹窗
- Console.WriteLine("任务已存在且处于启用状态,无需操作。");
- return;
- }
- try
- {
- string exePath = Process.GetCurrentProcess().MainModule.FileName;
- // 构建 schtasks 命令
- // /ru "" 表示以当前用户运行 (在某些Win11版本中,显式指定用户更稳定)
- // /rl highest 表示以最高权限运行
- // /sc onlogon 表示登录时触发
- // /f 强制覆盖已存在的任务
- string arguments = $"/create /tn \"{TaskName}\" /tr \"\\\"{exePath}\\\"\" /sc onlogon /rl highest /f";
- ProcessStartInfo startInfo = new ProcessStartInfo
- {
- FileName = "schtasks",
- Arguments = arguments,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- Verb = "runas" // 请求管理员权限
- };
- using (Process process = Process.Start(startInfo))
- {
- process.WaitForExit();
- if (process.ExitCode == 0)
- {
- Console.WriteLine("任务计划创建/更新成功");
- }
- else
- {
- string error = process.StandardError.ReadToEnd();
- Console.WriteLine($"创建失败: {error}");
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"异常: {ex.Message}");
- }
- }
- /// <summary>
- /// 删除开机自启任务
- /// </summary>
- public static void UnregisterTask()
- {
- // 可选:先检查是否存在,避免无意义的弹窗
- try
- {
- string checkArgs = $"/query /tn \"{TaskName}\"";
- ProcessStartInfo checkInfo = new ProcessStartInfo("schtasks", checkArgs)
- {
- UseShellExecute = false,
- CreateNoWindow = true
- };
- using (var p = Process.Start(checkInfo))
- {
- p.WaitForExit();
- if (p.ExitCode != 0)
- {
- Console.WriteLine("任务不存在,无需删除。");
- return;
- }
- }
- }
- catch { }
- try
- {
- string arguments = $"/delete /tn \"{TaskName}\" /f";
- ProcessStartInfo startInfo = new ProcessStartInfo
- {
- FileName = "schtasks",
- Arguments = arguments,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- Verb = "runas"
- };
- using (Process process = Process.Start(startInfo))
- {
- process.WaitForExit();
- if (process.ExitCode == 0)
- {
- Console.WriteLine("任务删除成功");
- }
- else
- {
- string error = process.StandardError.ReadToEnd();
- Console.WriteLine($"删除失败: {error}");
- }
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine($"删除任务失败: {ex.Message}");
- }
- }
- }
- }
|