本文介绍了 Zig 如何实现一个Windows 下进程感知与控制工具(ProcMonitor):核心是在检测到指定进程启动时,自动触发预定义动作(如关闭/启动其他进程)。
整体架构
按照分层基本做的整体划分
CLI → 配置 → 初始化 → 监控器监控器 → 拉取进程列表 → 状态机判断状态机 → 触发动作引擎动作引擎 → 调用 Windows API
| 层级 | 职责 |
|---|---|
| 入口层 | CLI解析、初始化系统组件 |
| 核心逻辑层 | 监控调度、状态判断、动作执行 |
| 基础设施层 | 配置、日志、路径处理 |
| 系统接口层 | 封装 Windows API |
架构图

核心流程
各阶段流程:
-
启动阶段
- CLI解析(配置路径、daemon、once)
- Fail-Fast:参数错误直接退出
-
初始化阶段
- 加载 TOML 配置
- 初始化日志(文件 + 控制台)
- 可选 daemon 化(隐藏窗口 + 解绑 console)
-
核心循环,每轮:
- 获取系统进程快照
- 遍历所有监控目标
- 匹配进程
- 根据状态判断是否触发动作
流程图

核心实现
配置使用TOML:
- 一条规则 = 一个被监控进程 + 一组动作
- 动作用 Map 表达:支持多目标、多动作
- 每个规则独立配置检查间隔(如游戏进程可以较长,工具类较短)
- 每条规则独立循环,互不干扰
ini
[[monitor.process]]
monitored = "steam.exe"
action = { "clash-verge.exe" = "close" }
check_interval = 10
启动逻辑
启动时错误处理
| 场景 | 处理 |
|---|---|
| 配置解析失败 | 直接退出 |
| API调用失败 | 返回错误并记录日志 |
| 无效路径 | 拒绝执行 |
scss
parse_args()
load_config()
init_logger()
if daemon:
daemonize()
monitor.init()
if once:
run_once()
else:
start_loop()
核心处理模块
状态驱动检测
scss
(process_name, pid) → 状态表 → 是否触发
关键数据结构
java
MonitorState:
monitored_process
detected_pids (HashMap)
check_interval
核心逻辑
css
for process in process_list:
if match(target):
if pid not in detected:
execute_actions()
mark_detected(pid)
行为/动作执行机制
动作类型
| 类型 | 行为 |
|---|---|
| close | 终止目标进程 |
| start | 启动新进程 |
执行流程
go
for action in actions:
if type == close:
terminateProcess()
else if type == start:
CreateProcessW()
状态管理 / 控制机制
状态设计策略
| 问题 | 解决方式 |
|---|---|
| 重复触发 | 记录 PID |
| 多实例 | HashMap |
| 状态漂移 | 每轮校准 |
状态图

构建与验证
构建运行
r
# 构建
zig build
# 单次执行
zig build run -- --once
# 指定配置
zig build run -- -c config.toml
# 后台运行
zig build run -- --daemon
示例配置
ini
daemon = false
[[monitor.process]]
monitored = "game.exe"
action = { "helper.exe" = "start" }
check_interval = 5