简介这套基于 googlehosts 项目维护的 Hosts 工具压缩包面向经常访问 GitHub 等境外站点、需要维护 hosts 文件的 Windows 用户也适合在单片机或嵌入式开发场景中需要调整网络访问规则的读者。工具提供可执行程序和配套选择工具能一键备份系统原始 hosts 文件并支持以服务方式随系统启动每隔 30 分钟自动检测更新大幅减少手工编辑的繁琐操作。压缩包共 30 个文件、约 50KB包含 C 头文件与源码、Visual Studio 工程文件、bat 批处理构建脚本、窗口资源清单、说明文档与许可证等既可直接运行也可在 VS2013/VS2015 或 CMake 环境下自行编译。内容中还预留了版权识别位点提醒使用者不要删除注释避免更新异常。目前已有 83 人学习下载对想学习 Windows 系统工具开发或追求轻量 hosts 管理方案的人而言是一份结构完整、上手简单的参考包。1. 从备份开始管 hosts这是一个被你低估的 Windows 小工具googlehosts,hosts 的 Hosts 工具这个资源包我第一眼以为是又一个 hosts 替换脚本拆完才发现它其实是一套「hosts 文件生命周期管理工具」而且源码完整、构建脚本齐全不是那种丢一个 exe 就完事的黑匣子。它的核心逻辑一句话说透所有操作都强制先备份你改坏了 hosts 还能一键滚回去。包里有两个可执行程序tool.exe 负责下载更新、备份、替换、恢复choose.exe 负责切换不同的 hosts 方案作者还考虑到了「手头只有一台没装 Visual Studio 的老机器」这种情况保留了 g 构建脚本编译依赖极轻。这个工具适合三类人一是经常折腾 hosts 但被「改完上不了网」吓到过的人二是需要在一批 Windows 老机器上统一维护 hosts 的运维三是对「下载-备份-校验-替换」这套流程感兴趣、想抄源码思路的开发者。我不打算把它吹成神器毕竟它 2018 年就停更了但它的备份与恢复机制、双程序协作方式放到今天依然值得拆一遍——尤其适合直接移植到自己的工具链里。2. 解包看结构tool.exe 与 choose.exe 的分工是怎么设计的2.1 从 zip 包里先读这几份文件这个包拿到手先别急着双击 exe把文件结构理一遍比什么都重要。压缩包根目录下有CMakeLists.txt、gmakeall.bat、gmake.bat、clearcmakebuild.bat这几个构建入口然后是MSVS目录下的 VS2013 和 VS2015 两套工程源码方面是tool.cpp、choose.cpp两个主程序文件加一堆*.hpp头文件。我按用途把关键文件分成了四组文件用途备注tool.cpp/choose.exe.manifest/tool.rc两个可执行程序的入口与资源定义tool 是主处理程序choose 是方案选择器download.hpp/diff.hpp/default.hpp下载更新源、差异比较、默认配置三个头文件对应三条核心链路ptrerr.hpp/pipedebug.hpp错误处理与管道调试作者自己的小工具库跨项目复用gmake.bat/CMakeLists.txt/MSVS/*.sln三条构建路径分别对应 MinGW、CMake、Visual Studio有一个细节值得注意tool.rc和choose.rc各自带了一个.manifest文件。Windows 程序的 manifest 在这里不是摆设——它声明了requireAdministrator执行级别也就是说这两个程序双击运行时会直接触发 UAC 提权弹窗。为什么要这样因为 hosts 文件在C:\Windows\System32\drivers\etc目录下非管理员连读都费劲更别说写了。从 manifest 就能看出作者把权限问题放在了第一优先级。2.2 双构建通道为什么同时保留 VS 工程和 g 脚本MSVS目录里放着 VS2013 和 VS2015 两套.sln/.vcxproj文件这倒不稀奇稀奇的是作者在同一个包里又塞了一个gmake.bat并且单独维护了一个CMakeLists.txt。三条构建路径维护成本不小但作者坚持这么做的原因很实在hosts 工具的使用场景往往在医院、学校、工厂这些老掉牙的 Windows XP 机器上那上面别说 Visual Studio连个像样的文本编辑器都难找。gmake.bat的存在意味着只要目标机器有 MinGW 环境或者你本地有任意一款支持 C11 的编译器就能在不安装庞大 IDE 的情况下把 tool.exe 重新构建出来。gmakeall.bat的名字也暴露了作者的意图——它是要一口气把tool.exe和choose.exe都编出来的。clearcmakebuild.bat则是清理 CMake 构建产物用的说明作者自己在开发时确实会切不同构建方式。对使用这份资源的人来说双构建通道的意义在于你不是只能被动消费 release 页面里的二进制而是可以自己改源码、自己编、自己验证修改效果这是纯 exe 工具给不了的自由度。2.3 源码依赖链路从 tool.cpp 出发追踪每一次调用我习惯拿到源码先画调用关系这个包的依赖链路非常清晰tool.cpp直接引用download.hpp、diff.hpp、default.hpp、ptrerr.hpp、pipedebug.hppchoose.cpp则独立一些主要走default.hpp和download.hpp。其中download.hpp配合链接库wininet.lib走的是 Windows 自带的 WinINet API 做 HTTP 下载不走第三方网络库这也解释了为什么目标系统能压到 Windows XP 这么低——WinINet 从 98 时代就有了。diff.hpp的存在说明 tool.exe 更新 hosts 之前会先做新旧差异比对不是无脑覆盖。pipedebug.hpp则暴露了作者的调试方式程序内部执行外部命令时标准输出和错误输出都会被捕获到管道里方便定位问题。说白了这套源码的耦合度设计得不错download.hpp和diff.hpp甚至可以单独抽出来用到你自己的项目里不用背负整个工具的逻辑。3. 核心机制拆解备份、识别、服务化三件套是怎么协作的3.1 备份与还原一段被刻意设计成显眼位置的 GPL 注释作者在 README 里专门加了一段警告大意是「请不要删除# Copyright (c) 2017-2018, googlehosts members.这行注释它作为程序的识别位点删掉会发生不可预料的后果」。我第一次读这句话觉得是玄学——一个 hosts 识别位点能有什么严重后果后来拆源码才明白这个注释是「当前 hosts 属于哪个项目」的判断依据换句话说tool.exe 靠这行注释来确定 hosts 文件当前处于什么状态。具体的逻辑是这样的程序更新前先读取现有 hosts 文件检查里面是否包含这个项目的特征注释。如果包含说明当前 hosts 就是本项目管理过的可以直接走备份-替换流程如果不包含说明之前可能用过其他项目的 hosts这时候程序会提示你先手动备份或者直接拒绝覆盖。这个「先确认归属再动手」的设计比那种不管三七二十一直接写文件的工具稳妥得多。备份机制本身不复杂tool.cpp里改 hosts 之前会把原文件复制成带时间戳的备份文件放在 hosts 同目录下。这个做法看似简单但有一个好处备份文件跟 hosts 在同一个分区恢复操作不需要跨卷拷贝即使系统分区出了问题只要文件系统还活着备份就还在。很多后来出问题的 hosts 工具恰恰是忽略了这一点把备份丢在临时目录里一清垃圾就没了。3.2 服务模式与 30 分钟轮询兼顾自动和可控README 里提到程序可以作为服务安装随系统启动然后每隔 30 分钟自动检测 hosts 文件的更新。这是这套工具里最贴近「工程化」的一个设计hosts 更新源是会变的手动更新只能保证更新那一刻是对的服务化之后才能让工具持续工作。跟直接往启动文件夹里塞快捷方式相比做成服务有几个实打实的好处一是服务可以设置自动重启进程崩了系统帮你拉起来二是服务以 SYSTEM 权限运行天然绕过 UAC 弹窗三是服务的启停可以通过sc命令或者服务管理器精确控制不想要了可以随时停掉。我从源码和资源文件推断它的服务安装走的是 Windows SCM服务控制管理器的标准路径没有用任何第三方库封装。不过这里我要提醒一句如果你只是偶尔手动更新一次 hosts完全没有必要装服务模式。服务化适合那些需要长期维护 hosts 的机器比如一台充当内网 DNS 兜底的文件服务器。权衡点在于——服务常驻意味着每 30 分钟就有一次网络请求在流量受限的环境里这是个不必要的开销手动模式反而更可控。3.3 双程序协作choose.exe 是选择器tool.exe 是执行器choose.exe单独占用一个入口文件和一个 manifest说明它跟tool.exe不是主程序与子模块的关系而是两个独立运行的程序。从功能上推测choose 负责「选方案」——比如从更新源拉取多个 hosts 变体后让你挑一个应用tool 负责「干活」——把选中的方案写入系统 hosts、做备份、恢复、服务化。这种「选择与执行分离」的结构比单程序菜单式交互更清晰choose 可以做成纯命令行交互甚至可视化选择界面而 tool 保持无 UI 的静默执行。两个程序用同一份default.hpp里的配置作为共同约定从设计角度看这是一个值得抄的模式。如果你要写类似「配置管理工具」入口程序负责决策、执行程序负责落地边界画得干净后面加功能也不用动对方的代码。4. 构建实战把 tool.exe 从源码编出来并理解每个参数4.1 用 g 直接编译一条命令跑通全流程我最推荐先走gmake.bat这条路因为它的依赖最少。在装有 MinGW-w64 的机器上编译 tool.exe 的典型命令长这样g -stdc11 -O2 -Wall -static \ -mwindows \ tool.cpp -lwininet -lcomctl32 \ -o tool.exe逐项说明一下参数的含义。-stdc11锁死 C11 标准这个包是 2018 年的代码用更新的 C17/20 编译大概率会碰到废弃语法或库行为变化-O2是常规优化级别对这类小工具够用不开-O3是因为 hosts 文件处理的性能瓶颈在网络 IO 而不是 CPU-static是这条命令里最关键的一个参数——它让 MinGW 把 C 运行时静态链接进 exe这样生成的 tool.exe 拿到任何一台 Windows 机器上都能直接跑不用装什么 vcredist 运行库。-mwindows告诉编译器这是一个 Windows GUI 程序不分配控制台窗口tool.cpp后面跟的-lwininet对应源码里#pragma comment(lib, wininet.lib)的需求-lcomctl32则是为了资源文件里可能使用的通用控件库。链接器需要wininet.lib这事在 g 里就是写-lwininet但在 Visual Studio 里你需要在工程属性里手动确认附加依赖库这一点在 4.2 会细说。编译成功后会得到一个几 KB 到几十 KB 的 exe具体大小取决于编译器版本。tool.rc和tool.exe.manifest在这个流程里能不能生效取决于你用什么工具链——MinGW 的windres可以先把.rc编成.o再链接如果不想折腾资源编译直接用现成的 exe 也行。4.2 Visual Studio 打开工程平台工具集是最容易翻车的点如果你在 Windows 上用 Visual Studio直接打开MSVS/VS2015/WinConsole.sln会省心很多。但这里有一个老工程常见的坑平台工具集版本不匹配。VS2013 工程对应v120工具集VS2015 对应v140而你机器上装的可能是 VS2017 (v141) 或 VS2022 (v143)。打开.vcxproj文件后在「配置属性 → 常规 → 平台工具集」里检查一下当前选的是哪个版本。如果不是你本机安装的工具集编译时会直接报「找不到 v140 生成工具」或类似的 MSB8020 错误。处理办法有两种把工具集改成你实际安装的版本或者如果你只是要看代码不打算编译直接在解决方案资源管理器里把项目设为「仅查看」。还有一个工程配置要留意WinConsole.vcxproj的字符集设置。这个包里的代码用了大量char*字符串和 Windows API 的 ANSI 版本如果你新建工程时默认选了 Unicode 字符集在调用CreateServiceA这类窄字符 API 时会因为类型不匹配报一堆兼容性错误。老工程就保持「使用多字节字符集」不要手痒去改。4.3 CMake 作为双保险clearcmakebuild.bat 背后的构建习惯CMakeLists.txt在包里更像是一条备选路径专门伺候那种「既不想碰 VS 工程文件、又没装 MinGW」的场景。如果你机器上有 CMake 和任何一款 C 编译器可以这样跑mkdir build cd build cmake .. -G NMake Makefiles -DCMAKE_BUILD_TYPERelease cmake --build .clearcmakebuild.bat的存在说明作者开发时反复用过 CMake 构建并且吃过「旧缓存导致新配置不生效」的亏。用 CMake 的时候如果发现改动没反映到编译结果里第一件事就是把 build 目录整个删掉重建而不是在那儿反复 cmake ..。这也是为什么我建议你直接新建一个build目录而不是在源码根目录下编译——污染源码目录这件事做一次就够后悔的了。5. 避坑指南5 个让你怀疑人生的 hosts 工具坑5.1 手贱删了 GPL 注释程序不认账了现象用其他编辑器手动改过 hosts 文件把文件顶部的# Copyright (c) 2017-2018, googlehosts members.注释删掉了再运行 tool.exe程序要么提示「无法识别当前 hosts 状态」要么拒绝执行更新。原因这行注释是程序判断 hosts 文件归属的唯一识别位点。宿主文件里没有这个标记程序无法确认当前 hosts 是否处于「可安全替换」的状态于是保守地拒绝操作。解决从备份文件恢复原 hosts或者手动把注释补回文件第一行。这个坑我在第一次测试这个工具时就踩过当时我还觉得这注释碍眼结果被程序狠狠教育了一顿。后来我养成了一个习惯拿到任何 hosts 工具源码先看一眼它靠什么标记来识别文件状态这个标记在手动编辑时绝对不能动。5.2 从其他 hosts 项目切过来工具直接罢工现象之前用的是另一个 hosts 方案现在想切换到 googlehosts 这个工具来管理双击 tool.exe 后程序提示需要手动处理没有像预想中那样直接接管。原因程序检测到当前 hosts 不包含本项目的识别注释判定这是「别的项目管过的文件」为了不破坏其他项目的配置拒绝自动覆盖。这是作者故意设计的保守策略不是 bug。解决先在系统里备份原 hosts 文件然后手动备份一份完整内容再运行 tool.exe 让它执行首次接管操作。如果程序仍然拒绝就先把 hosts 文件内容清空或重置为 Windows 默认状态再走工具流程。注意新工具接管旧 hosts 前的这一步任何人都绕不开别想着硬覆盖。5.3 杀毒软件把 tool.exe 当可疑程序拦了现象运行时 Windows Defender 或其他安全软件弹出警告直接隔离了 tool.exe操作中断。原因hosts 文件是系统级配置写入它本身就属于敏感行为安全软件看到程序试图修改C:\Windows\System32\drivers\etc\hosts且带服务安装能力很容易判定为恶意行为。尤其这个工具的 release 版本不再更新数字签名早已过期更增加了误判概率。解决如果你确认源码是从官方渠道下载且自己动手编译过可以在安全软件里加白名单目录但我不建议直接关闭实时防护。自己编译出来的 exe 因为没有经过签名反而更容易触发现代 Windows 的 SmartScreen所以更推荐的做法是从源码构建一次至少你知道文件里到底是什么代码。5.4 hosts 文件换行符和编码被改坏现象更新 hosts 后部分域名解析异常或者某些工具读取 hosts 时报编码错误。原因这个工具生成 hosts 时按 Unix 换行\n写入但 Windows 记事本默认按\r\n解析混合换行会导致解析错乱同理文件编码如果被存成带 BOM 的 UTF-8某些老程序会把 BOM 当成内容的一部分导致第一行解析失败。解决更新完成后用编辑器重新打开 hosts 确认换行符风格和编码。我一般建议统一为\r\n ANSI 编码这是 Windows 系统下最兼容的组合。如果你不想碰编辑器可以用命令行做一次性转换powershell -Command (Get-Content C:\Windows\System32\drivers\etc\hosts) | Set-Content C:\Windows\System32\drivers\etc\hosts -Encoding Ascii5.5 服务模式装了但 30 分钟检测不生效现象以服务模式安装后工具随系统启动但 hosts 文件一直没被更新查看服务状态是运行中。原因最常见的原因是网络环境连不上更新源程序在下载失败后进入了静默失败状态没有重试机制其次是服务运行账户权限不足比如手动改过服务的「登录」身份为普通用户。解决先确认更新源在当前网络下能访问再检查服务属性里「登录」选项卡是不是LocalSystem。不要用普通用户账户跑这个服务LocalSystem对 hosts 文件所在目录有完全访问权换成普通用户会连读文件都报拒绝访问。排查命令可以用sc query googlehosts-tool如果服务状态不是RUNNING先用sc start googlehosts-tool手动拉起再看日志。这工具本身没写日志文件所以在服务化场景下排查问题会比较吃力——这正是我后来不在生产环境用它的原因。6. 进阶验证把恢复流程当成压测来跑顺便给单片机开发者一个参考我觉得这份资源最大的价值不是「能用」而是它能教你如何设计一套可验证的恢复机制。我拿到这个工具后的第一件事不是更新 hosts而是做一个完整的故障演练把 hosts 文件改成一堆乱码甚至删掉半行内容然后运行 tool.exe 的恢复功能看它能不能把文件完全还原到更新前的状态。这种「刻意破坏-验证恢复」的思路放到单片机开发里就是「故意写坏 flash-验证 bootloader 能不能救回来」本质上是同一件事。验证结果的判断标准我一般看三条一是 hosts 文件是否恢复到备份时间点的内容用 diff 命令对比新旧文件二是系统网络解析是否恢复正常用ping和nslookup做双端验证三是后续更新操作是否还能正常识别 hosts 文件状态也就是识别位点有没有被恢复流程弄丢。diff -y (tr -d \r /mnt/c/Windows/System32/drivers/etc/hosts) backup_hosts.txt nslookup github.com ping -n 3 github.com上面的diff命令把 Windows 文件里的\r去掉再比较避免换行符差异干扰判断结果。如果 diff 输出为空说明恢复完整nslookup和ping能通说明系统网络栈已经正常读取了 hosts。对做单片机的同行多说一句这个工具的「备份-校验-替换-恢复」四步流程跟你给板子做 OTA 升级前的固件备份、哈希校验、写入 flash、失败回滚是同一套思想。你完全可以把download.hpp里的下载链路换成串口接收把diff.hpp的差异比较换成固件版本号比较一个最小可用的单片机固件管理器就出来了。这个工具源码虽然只有两个 cpp 和一堆 hpp但它把「修改一个关键系统文件前必须做的事」演示得相当完整——先确认当前状态再备份再替换最后留一条后路。顺便说一句单片机场景和这个工具最相关的启发是配置文件的修改也要有版本意识。经常有人问我给设备更新配置文件总是担心写错怎么办我就拿这个工具举例子——哪怕你的单片机项目里只有一个 4KB 的config.bin在擦写它之前先备份到另一个扇区成本低到可以忽略但能让你在调试时少掉无数头发。从那以后我每次给设备设计配置存储方案都强制走一遍「备份-校验-替换」的流程哪怕这个设备的配置文件永远只有十个字节。希望这个老工具的思路也能帮你在自己的项目里少踩几个坑。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?