仓库:MuZiCul/win-net(原创)· 语言:C# / .NET 8 · 定位:常驻后台、零依赖、极小资源占用的 Windows 网络修复工具
WinNetFix 是一个面向 Windows 桌面用户的"网络保姆"。主用有线网络,WiFi 作为常备通道自动守护——有线卡死自动重启网卡、WiFi 断开自动重连、DNS 故障自动修复、GitHub 连接被污染自动修复,全程后台运行。
Program.cs)单实例保证:
private const string MutexName = @"Global\WinNetFix_SingleInstance";
public const string TaskName = "WinNetFix";
public static string LogDir => Path.Combine(AppContext.BaseDirectory, "logs");
用 Global\ 前缀的命名 Mutex 防止重复启动——注意 Global\ 前缀意味着跨用户会话生效,这对"计划任务以最高权限运行"的场景是必须的。
编码处理(中文环境必备):
Console.OutputEncoding = Encoding.UTF8;
// 注册代码页 provider:支持 GBK/936(hosts 中文注释、netsh 中文输出解码)
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
.NET Core 默认不带 GBK 编码,不注册的话读取中文 hosts 或解析 netsh 中文输出会乱码。这个细节说明作者踩过坑。
权限模型(分层设计):
switch (first)
{
case "--install": case "--uninstall": case "--once": case "--run":
case "--wifi-on": case "--wifi-off": case "--github-fix": case "--github-restore":
default:
// 需要管理员权限的模式:非管理员时自动 UAC 提权重启
if (!IsAdministrator() && TryElevateSelf(args))
return 0; // 提权成功,旧进程退出
WarnIfNotAdmin(); // 提权被拒 → 回退普通权限运行
break;
case "--status":
break; // 只读探测,无需提权
}
三种处理路径:计划任务自启(无 UAC)→ 手动运行(弹 UAC)→ --status 只读(免提权)。提权被拒也能降级继续运行,不直接崩溃。
GithubHosts.Diagnose())var diag = GithubHosts.Diagnose(_log).GetAwaiter().GetResult();
Console.WriteLine($" TCP443(本机IP): {(diag.GithubReachable ? "可达" : "不可达")}");
Console.WriteLine($" 本机解析: {string.Join(", ", diag.LocalIps)}");
Console.WriteLine($" DoH真值: {string.Join(", ", diag.TrueIps)}");
Console.WriteLine($" 判定: {(diag.DnsPolluted ? "DNS 已污染 → 需要修复" : "未检测到污染 → 尝试修复")}");
诊断原理:比对"本机 DNS 解析结果"与"DoH(阿里/Google)真实结果"——不一致即判定污染。修复流程是:多源 DoH 并行解析 → TCP 443 测速选最优 → 写入 hosts(标记段管理、可一键还原、首次写入自动备份)。
| 命令 | 功能 |
|---|---|
--run |
常驻后台(隐藏窗口,默认) |
--install / --uninstall |
注册/注销开机自启计划任务 |
--once |
执行一次完整探测+修复流程(调试用) |
--status |
查看当前网络状态(只读,无需提权) |
--wifi-on / --wifi-off |
手动开关 WiFi 软件开关 |
--github-fix / --github-restore |
修复 GitHub 连接 / 还原 hosts |
--version / -v |
输出版本号 |
--config <path> |
指定配置文件路径 |
%ProgramData%\WinNetFix\config.json){
"probe": {
"intervalSec": 15, // 探测间隔
"failThreshold": 2, // 连续失败阈值
"timeoutMs": 3000, // 单次探测超时
"gatewayIcmp": true, // 网关 ICMP(判定本地链路)
"publicIcmpTarget": "8.8.8.8",
"dnsHttpUrl": "https://www.msftconnecttest.com/connecttest.txt"
},
"repair": {
"restartAdapter": true,
"flushDns": true,
"fallbackPublicDns": true,
"publicDns": ["8.8.8.8", "223.5.5.5"],
"reconnectWifi": true,
"wifiRetryCooldownSec": 60,
"preferredSsid": "", // 空 = 用最后连接/首个 profile
"maxRetry": 3,
"backoffSec": [5, 15, 30]
},
"log": { "level": "Info", "retentionDays": 30 }
}
| 故障 | 处理方式 | 设计考量 |
|---|---|---|
| 有线卡死(Up 但无网) | 禁用/启用网卡 | — |
| WiFi 未连接(含软开关关) | 自动开开关 + 连已存 SSID | 已连接则不触碰 |
| DNS 故障 | ipconfig /flushdns → 切公共 DNS |
分层判定:ICMP → DNS → HTTP |
| 169.254(DHCP 失败) | ipconfig /release + /renew |
不重启网卡(会打断 DHCP) |
| 连续失败 | 冷却 30 分钟后再重试 | 防抖防死循环,但非永久停手 |
| HTTP 被拦(SSL/防火墙) | 不修复,仅记录 | 应用层故障不误修 |
| 类 | 职责 |
|---|---|
Program.cs |
入口、参数解析、UAC 提权、命令分发 |
AdapterManager.cs |
网卡启停 |
DnsManager.cs |
DNS 分层诊断与修复 |
WlanManager.cs + WlanApi.cs |
WiFi 管理与 Windows WLAN API 封装 |
GithubHosts.cs |
GitHub 连接诊断与 hosts 修复 |
ProbeLayer.cs |
网络分层探测 |
StateMachine.cs |
防抖/冷却状态机 |
TrayApp.cs / TrayIcon.cs |
托盘菜单 |
ProgressWindow.cs |
彩色富文本进度窗口 |
Config.cs / ConfigJsonContext.cs |
配置加载(System.Text.Json 源生成) |
Logger.cs |
日志(按天滚动、保留 N 天) |
ProcessRunner.cs |
外部进程执行封装 |
.\publish.ps1 → publish/WinNetFix.exe(self-contained,免装 .NET)WinNetFix-Setup-X.Y.Z.exe,安装到 C:\Program Files\WinNetFix\,自动注册开机自启这个工具是我的项目里完成度较高、实战经验较多的,下面几点是我觉得值得一提的设计:
我在做 Windows 系统级工具和 .NET 桌面应用时,这个项目就是照着它自己搭的。