using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace FastGithub.Dns.DnscryptProxy { /// /// DnscryptProxy后台服务 /// sealed class DnscryptProxyHostedService : BackgroundService { private bool isStopped = false; private const string dnscryptProxyFile = "dnscrypt-proxy"; private readonly ILogger logger; /// /// DnscryptProxy后台服务 /// /// public DnscryptProxyHostedService(ILogger logger) { this.logger = logger; } /// /// 启动dnscrypt-proxy /// /// /// public override Task StartAsync(CancellationToken cancellationToken) { try { if (OperatingSystem.IsWindows()) { StartDnscryptProxy("-service install", waitForExit: true); StartDnscryptProxy("-service start", waitForExit: true); } else { StartDnscryptProxy(string.Empty, waitForExit: false); } this.logger.LogInformation($"{dnscryptProxyFile}启动成功"); } catch (Exception ex) { this.logger.LogWarning($"{dnscryptProxyFile}启动失败:{ex.Message}"); } return base.StartAsync(cancellationToken); } /// /// 后台监控 /// /// /// protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Yield(); var process = Process.GetProcessesByName(dnscryptProxyFile).FirstOrDefault(); if (process != null) { process.WaitForExit(); } if (this.isStopped == false) { this.logger.LogCritical($"{dnscryptProxyFile}已停止运行,{nameof(FastGithub)}将无法解析域名。你可以把配置文件的PureDns修改为其它可用的DNS以临时使用。"); } } /// /// 停止dnscrypt-proxy /// /// /// public override Task StopAsync(CancellationToken cancellationToken) { try { this.isStopped = true; if (OperatingSystem.IsWindows()) { StartDnscryptProxy("-service stop", waitForExit: true); StartDnscryptProxy("-service uninstall", waitForExit: true); } foreach (var process in Process.GetProcessesByName(dnscryptProxyFile)) { process.Kill(); } this.logger.LogInformation($"{dnscryptProxyFile}已停止"); } catch (Exception ex) { this.logger.LogWarning($"{dnscryptProxyFile}停止失败:{ex.Message}"); } return base.StopAsync(cancellationToken); } /// /// 启动DnscryptProxy进程 /// /// /// private static void StartDnscryptProxy(string arguments, bool waitForExit) { var process = Process.Start(new ProcessStartInfo { FileName = OperatingSystem.IsWindows() ? $"{dnscryptProxyFile}.exe" : dnscryptProxyFile, Arguments = arguments, UseShellExecute = true, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }); if (waitForExit && process != null) { process.WaitForExit(); } } } }