using System.Diagnostics; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using SHH.CameraSdk; namespace SHH.CameraService; public class ParentProcessSentinel : BackgroundService { private readonly ServiceConfig _config; private readonly IHostApplicationLifetime _lifetime; private readonly ILogger _logger; public ParentProcessSentinel( ServiceConfig config, IHostApplicationLifetime lifetime, ILogger logger) { _config = config; _lifetime = lifetime; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { int pid = _config.ParentPid; // 如果 PID 为 0 或负数,说明不需要守护(可能是手动启动调试) if (pid <= 0) { _logger.LogInformation("未指定有效的父进程 PID,守护模式已禁用。"); return; } _logger.LogInformation($"父进程守护已启动,正在监控 PID: {pid}"); while (!stoppingToken.IsCancellationRequested) { if (!IsParentRunning(pid)) { _logger.LogWarning($"[ALERT] 检测到父进程 (PID:{pid}) 已退出!正在终止当前服务..."); // 触发程序优雅退出 _lifetime.StopApplication(); // 强制跳出循环 break; } // 每 2 秒检查一次,避免 CPU 浪费 await Task.Delay(2000, stoppingToken); } } private bool IsParentRunning(int pid) { try { // 尝试获取进程对象 var process = Process.GetProcessById(pid); // 检查是否已退出 if (process.HasExited) return false; return true; } catch (ArgumentException) { // GetProcessById 在找不到 PID 时会抛出 ArgumentException // 说明进程已经不存在了 return false; } catch (Exception ex) { _logger.LogError(ex, "检查父进程状态时发生未知错误,默认为存活"); return true; // 发生未知错误时,保守起见认为它还活着 } } }