如何获取子进程的句柄 uintptr?

How do I get a handle uintptr of a child process?

我想启动一个子进程(我在 windows 10),我希望能够随意暂停和恢复该进程。

我从 ntdll.dll 中找到了这个简洁的未记录的 windows 函数 NtSuspendProcess 应该可以完成这项工作,但现在我需要获取进程的句柄来发出挂起命令。

这是一个例子:

modntdll = syscall.NewLazyDLL("ntdll.dll")
procNtSuspendProcess = modntdll.NewProc("NtSuspendProcess")
procNtResumeProcess  = modntdll.NewProc("NtResumeProcess")
_, _, err = procNtSuspendProcess.Call(uintptr(handle))
_, _, err = procNtResumeProcess.Call(uintptr(handle))

要启动进程,我通常会使用 exec.Command 函数,但我找不到检索进程句柄的方法。

有没有办法在启动进程时获取句柄?
如果不使用 exec.Command,我应该使用什么其他库来启动 returns 也是进程处理的进程?

作为旁注:
我已经研究过 syscall.StartProcess,但它的水平很低,我觉得无法处理这样的原始实现。

_, handle, err := syscall.StartProcess("C:\WINDOWS\system32\cmd.exe", []string{}, procAttr)

Go 不会在 exec.Command 中公开公开句柄,您必须通过以下方式访问它。

反思

cmd := exec.Command("cmd.exe")
cmd.Start()
handle := uintptr(reflect.ValueOf(cmd.Process).Elem().FieldByName("handle").Uint())

或者通过创建相同的流程类型并将 Cmd.Process 转换为您自己的类型以访问私有字段。

type Process struct {
   Pid int
   handle uintptr
   isdone uint32
   sigMu sync.RWMutex
}
cmd := exec.Command("cmd.exe")
cmd.Start()
proc := (*Process)(unsafe.Pointer(cmd.Process))
println(proc.handle)

“Make that 4”的 完美无缺,简单易懂。

为了完整起见,我只想添加一个我发现的额外方法(需要导入 golang.org/x/sys/windows
更新:显然这个方法可能会导致 bugs/errors,最好不要实现它(查看评论)

cmd := exec.Command("cmd.exe")
cmd.Start()

// using PROCESS_SUSPEND_RESUME since I want to call NtSuspendProcess function
handle, _ := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(cmd.Process.Pid))
defer windows.CloseHandle(handle)

fmt.Println(handle)