Files
remote-core/process/killtree_windows.go
T
w11 c7dd0d9c6b fix(process): kill 兜底弃 taskkill 命令行, 改 Windows API 进程树强杀
- Toolhelp32 快照枚举父子关系→收集后代(防环)→OpenProcess+TerminateProcess 按 PID 定向结束
- 产品红线: 系统操作禁拼 cmd 命令字符串(2026-10-09 用户令, 与 zomaintain AGENTS §一同源)
- wire 不变: 仅错误文案 taskkill 段改'进程树终止'
2026-10-09 22:01:00 +08:00

79 lines
1.9 KiB
Go

//go:build windows
// 进程树强杀(编程方式, Windows API)——2026-10-09 起替代原 taskkill /F /T 命令行兜底
// (产品红线: 系统操作禁拼 cmd 命令字符串)。
package process
import (
"fmt"
"unsafe"
"golang.org/x/sys/windows"
)
// killProcessTree 按 PID 定向结束进程及其全部后代:
// Toolhelp32 快照枚举全进程父子关系 → 收集后代(防父子环) → 逐个 OpenProcess+TerminateProcess。
func killProcessTree(root uint32) error {
parentOf, err := snapshotParentMap()
if err != nil {
return err
}
var pids []uint32
visited := map[uint32]bool{}
var visit func(pid uint32)
visit = func(pid uint32) {
if visited[pid] {
return
}
visited[pid] = true
pids = append(pids, pid)
for child, parent := range parentOf {
if parent == pid {
visit(child)
}
}
}
visit(root)
var firstErr error
for _, pid := range pids {
h, err := windows.OpenProcess(windows.PROCESS_TERMINATE, false, pid)
if err != nil {
if firstErr == nil {
firstErr = fmt.Errorf("pid=%d OpenProcess: %w", pid, err)
}
continue
}
if err := windows.TerminateProcess(h, 1); err != nil {
if firstErr == nil {
firstErr = fmt.Errorf("pid=%d TerminateProcess: %w", pid, err)
}
}
_ = windows.CloseHandle(h)
}
return firstErr
}
// snapshotParentMap 全进程快照: pid → 父 pid。
func snapshotParentMap() (map[uint32]uint32, error) {
snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)
if err != nil {
return nil, fmt.Errorf("CreateToolhelp32Snapshot: %w", err)
}
defer windows.CloseHandle(snap)
parentOf := map[uint32]uint32{}
var pe windows.ProcessEntry32
pe.Size = uint32(unsafe.Sizeof(pe))
if err := windows.Process32First(snap, &pe); err != nil {
return nil, fmt.Errorf("Process32First: %w", err)
}
for {
parentOf[pe.ProcessID] = pe.ParentProcessID
if err := windows.Process32Next(snap, &pe); err != nil {
break
}
}
return parentOf, nil
}