英文:
How do I get a handle uintptr of a child process?
问题
我想启动一个子进程(我在Windows 10上),并且希望能够随时挂起和恢复该进程。
我找到了一个很好的未记录的Windows函数NtSuspendProcess
,它来自于ntdll.dll
,应该可以完成这个任务,但是现在我需要获取进程的句柄来发出挂起命令。
这是一个示例:
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
,但它是相当底层的,我不太能够处理这样的原始实现。
_, handle, err := syscall.StartProcess("C:\\WINDOWS\\system32\\cmd.exe", []string{}, procAttr)
英文:
I want to start a child process (i'm on windows 10) and I would like to be able to suspend and resume the process at will.
I found this neat undocumented windows function NtSuspendProcess
from ntdll.dll
that should do the job but now I need to get the handle of the process to issue the suspend command.
this is an example:
modntdll = syscall.NewLazyDLL("ntdll.dll")
procNtSuspendProcess = modntdll.NewProc("NtSuspendProcess")
procNtResumeProcess = modntdll.NewProc("NtResumeProcess")
_, _, err = procNtSuspendProcess.Call(uintptr(handle))
_, _, err = procNtResumeProcess.Call(uintptr(handle))
To start the process I would normally use the exec.Command
function but I can't find a way to retrieve the handle of the process.
Is there a way to get the handle when starting a process?
If not with exec.Command
, what other library should I use to start a process that returns also the process handle?
As a side note:
I've looked into syscall.StartProcess
but it's quite low level and I don't feel able to handle such a raw implementation.
_, handle, err := syscall.StartProcess("C:\\WINDOWS\\system32\\cmd.exe", []string{}, procAttr)
答案1
得分: 1
Go在exec.Command
中不公开暴露句柄,你可以通过以下方式访问它:
反射
cmd := exec.Command("cmd.exe")
cmd.Start()
handle := uintptr(reflect.ValueOf(cmd.Process).Elem().FieldByName("handle").Uint())
或者通过创建一个相同的Process类型,并将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)
英文:
Go does not publicly expose the handle in exec.Command
, you will have to access it either by.
Reflection
cmd := exec.Command("cmd.exe")
cmd.Start()
handle := uintptr(reflect.ValueOf(cmd.Process).Elem().FieldByName("handle").Uint())
or by creating an identical Process type and casting the Cmd.Process to your own type to access the private fields.
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)
答案2
得分: 0
"Make that 4"的答案无可挑剔,简洁明了。
我只想补充一个我找到的额外方法,以保证完整性(需要导入golang.org/x/sys/windows
)
更新:显然,这种方法可能会导致错误/bug,最好不要实现它(请查看评论)
cmd := exec.Command("cmd.exe")
cmd.Start()
// 使用PROCESS_SUSPEND_RESUME,因为我想调用NtSuspendProcess函数
handle, _ := windows.OpenProcess(windows.PROCESS_SUSPEND_RESUME, false, uint32(cmd.Process.Pid))
defer windows.CloseHandle(handle)
fmt.Println(handle)
英文:
The answer by "Make that 4" were both flawless, being simple and well explained.
I would just add an additional method that I found, just for completeness (requires the import of golang.org/x/sys/windows
)
Update: apparently this method might lead to bugs/errors and it's probably better not to implement it (check the comments)
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论