using System.Text.Json; using GatewayKeepalive.Core; namespace GatewayKeepalive.Windows; public static class DiagnosticCommands { public static async Task RunAsync(string[] args) { string? Value(string name) { var i = Array.IndexOf(args, name); return i >= 0 && i + 1 < args.Length ? args[i + 1] : null; } object report; var exitCode = 0; try { var backend = new WindowsNetworkBackend(); var adapters = await backend.ListAdaptersAsync(CancellationToken.None); var settingsPath = Value("--config") ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "GatewayKeepalive", "settings.json"); var settings = File.Exists(settingsPath) ? JsonSerializer.Deserialize(File.ReadAllText(settingsPath), JsonStore.Options) ?? throw new InvalidDataException("配置为空。") : new(); if (Value("--adapter") is { } adapter) settings = settings with { AdapterId = Guid.Parse(adapter), Configured = true }; backend.ConfigureIdentity(settings); var snapshots = new List(); foreach (var item in adapters.Where(x => settings.AdapterId == Guid.Empty || x.Id == settings.AdapterId)) { try { snapshots.Add(await backend.CaptureAsync(item.Id, CancellationToken.None)); } catch (Exception e) { snapshots.Add(new { Adapter = item, Error = e.Message }); } } object? plan = null; HealthReport? health = null; if (args.Contains("--dry-run") || args.Contains("--probe")) { settings.Validate(); var snapshot = await backend.CaptureAsync(settings.AdapterId, CancellationToken.None); var probe = new NetworkHealthProbe(backend.ValidateRoute); if (args.Contains("--probe")) health = await probe.CheckAsync(settings, snapshot, CancellationToken.None); if (args.Contains("--dry-run")) { var service = new SwitchService(backend, probe, new JsonStore(Path.GetDirectoryName(settingsPath)!), _ => { }); plan = service.Plan(settings, snapshot, !args.Contains("--direct"), snapshot.Gateway == settings.DirectGateway && settings.PreserveOriginalDirectDns ? snapshot.Dns : null); } } object? bestRoute; try { bestRoute = backend.DescribeBestRoute("1.1.1.1"); } catch (Exception e) { bestRoute = new { Error = e.Message }; } report = new { ReadOnly = true, IsAdministrator = backend.IsAdministrator, NativeLayout = WindowsNetworkBackend.NativeLayout(), Adapters = adapters, Snapshots = snapshots, BestRoute = bestRoute, PlannedConfiguration = plan, Health = health }; } catch (Exception e) { report = new { ReadOnly = true, Error = e.Message, Diagnostic = args.Contains("--verbose") ? e.ToString() : null }; exitCode = 1; } var json = JsonSerializer.Serialize(report, JsonStore.Options); if (Value("--output") is { } path) { Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path))!); await File.WriteAllTextAsync(path, json); } Console.WriteLine(json); return exitCode; } }