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

Windows 如何获取子进程的句柄uintptr?,windows,go,process,handle,suspend,Windows,Go,Process,Handle,Suspend,我想启动一个子进程(我在windows 10上),并且我希望能够随意暂停和恢复该进程 我在ntdll.dll中找到了这个整洁的、没有文档记录的windows函数NtSuspendProcess,它应该可以完成这项工作,但现在我需要获得进程的句柄来发出suspend命令 这是一个例子: modntdll = syscall.NewLazyDLL("ntdll.dll") procNtSuspendProcess = modntdll.NewProc("NtSuspen

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

我在
ntdll.dll
中找到了这个整洁的、没有文档记录的windows函数
NtSuspendProcess
,它应该可以完成这项工作,但现在我需要获得进程的句柄来发出suspend命令

这是一个例子:

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
,我应该使用哪个库来启动同时返回进程句柄的进程

作为旁注:
我已经研究了
syscall.StartProcess
,但它的级别很低,我觉得无法处理这样一个原始的实现


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
}
“makethat4”的设计既简单又解释得很好,完美无瑕

为了完整起见,我只想添加一个我发现的附加方法(需要导入
golang.org/x/sys/windows

更新:显然,这种方法可能会导致bug/错误,最好不要实现它(查看注释)


非常感谢你!如果你必须在这两种方法中选择一种,哪一种是最好的?最安全的?最有效?这两种方法可能的优缺点是什么?反射速度较慢,如果他们将其从句柄重命名为其他名称,反射就会中断(对此高度怀疑)。我不喜欢在我自己的代码中使用反射(个人选择)。指针转换在规范下是完全有效的,前提是您要转换的内容不大于您要从中转换的内容(内存方面),并且两者共享等效的内存布局。如果他们决定在Pid和handle之间添加一个字段,它就会中断(再次高度怀疑)。我见过一些其他的项目做这个把戏,所以如果真的发生了,你并不孤单。好的,非常感谢你的解释,如果
os.Process
struct应该被修改,我只需要修改我自己对
Process
struct(镜像原始结构)的声明,对吗?这里有一个竞争条件,由于PID也可以在您的答案中重复使用(它们不像句柄那样具有与流程本身分离的生命周期),因此句柄值在您打印时不再有意义。感谢您的反馈!为了清楚起见,我会留下这个答案,我会参考你的评论it@BenVoigt那么“让它变成4”的答案呢?它也有同样的问题吗?
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)
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)