实现 .NET 10 托盘版网关保活
包含分层探测、可补偿的 IPv4 路由/DNS 切换、自动策略、托盘与分组设置界面、只读诊断工具、离线测试和发布脚本。
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
using System.Text.Json;
|
||||
using GatewayKeepalive.Core;
|
||||
|
||||
namespace GatewayKeepalive.Windows;
|
||||
|
||||
public static class DiagnosticCommands
|
||||
{
|
||||
public static async Task<int> 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<AppSettings>(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<object>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user