如何解决知道父进程的句柄,如何获取子进程句柄?
在 Windows 10 上,我想在每个子/孙子进程上使用 <root>
<name><s>Light and dark</s></name>
<address>
<sector>142</sector>
<location>Noida</location>
</address>
</root>
挂起整个进程树。
我使用 NtSuspendProcess
启动父进程,进程树应如下所示:
exec.Command("java",...)
我可以使用以下命令检索进程父句柄 uintptr:
myapp (executes cmd.Start())
\__java (parent)
\__java
|__proc1
\__proc2
我不知道如何从父句柄(或 pid)中检索子进程的句柄,以便单独挂起它们。
(由于不存在将所有父进程和子进程一起暂停的选项,我应该一一暂停吗?)
- 我尝试列出所有进程,然后仅选择具有正确父 pid 的进程,但是我找不到通过知道子 pid 来可靠地获取父 pid 的方法(另外,在孙进程的情况下会出现问题,另外我更喜欢只使用手柄,这应该更可靠)。
- 我尝试创建一个生成第一个进程的作业,以便能够使用作业的句柄列出所有子 pid/句柄,但它非常复杂,需要一些低级实现(不需要非常适合
cmd := exec.Command("java",...) cmd.Start() // mirror os.Process struct type osprocmirror struct { Pid int handle uintptr isdone uint32 sigMu sync.RWMutex } handle := (*osprocmirror)(unsafe.Pointer(cmd.Process))
包)。 - 我从
os.exec
中找到了一个名为user32.dll
的 windows 函数并开始实现它,但由于我不完全理解它是如何工作的(它是否只适用于具有图形窗口的进程?因为我根本不使用 GUI),我想知道其他可能的解决方案(也许更简单)。
有没有更简单的方法可以从父句柄获取所有子进程句柄?
如果没有,您是否有此类实现的好例子?
谢谢
解决方法
我创建了一个小脚本来实现这一点(检查 here)
我会在这里发布:
// This is a script to retrieve the child processes pids of a process (retrieve the complete process tree)
// Tn this example the process identified by pid 7400 is used
// (please to run the test chose a process pid that has at least 1 child process)
// (tested on windows)
package main
import (
"fmt"
"syscall"
"unsafe"
)
func main() {
rootPid := uint32(7400)
tree,err := getTreePids(rootPid)
if err != nil {
fmt.Println(err)
}
fmt.Println("tree [",len(tree),"]:\t",tree)
}
// getTreePids will return a list of pids that represent the tree of process pids originating from the specified one.
// (they are ordered: [parent,1 gen child,2 gen child,...])
func getTreePids(rootPid uint32) ([]uint32,error) {
// https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/ns-tlhelp32-processentry32
procEntry := syscall.ProcessEntry32{}
parentLayer := []uint32{rootPid}
treePids := parentLayer
foundRootPid := false
snapshot,err := syscall.CreateToolhelp32Snapshot(uint32(syscall.TH32CS_SNAPPROCESS),0)
if err != nil {
return nil,err
}
defer syscall.CloseHandle(snapshot)
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
for {
// set procEntry to the first process in the snapshot
err = syscall.Process32First(snapshot,&procEntry)
if err != nil {
return nil,err
}
// loop through the processes in the snapshot,if the parent pid of the analyzed process
// is in in the parent layer,append the analyzed process pid in the child layer
var childLayer []uint32
for {
if procEntry.ProcessID == rootPid {
foundRootPid = true
}
if contains(parentLayer,procEntry.ParentProcessID) {
// avoid adding a pid if it's already contained in treePids
// useful for pid 0 whose ppid is 0 and would lead to recursion (windows)
if !contains(treePids,procEntry.ProcessID) {
childLayer = append(childLayer,procEntry.ProcessID)
}
}
// advance to next process in snapshot
err = syscall.Process32Next(snapshot,&procEntry)
if err != nil {
// if there aren't anymore processes to be analyzed,break out of the loop
break
}
}
// if the specified rootPid is not found,return error
if !foundRootPid {
return nil,fmt.Errorf("specified rootPid not found")
}
// fmt.Println(childLayer)
// there are no more child processes,return the process tree
if len(childLayer) == 0 {
return treePids,nil
}
// append the child layer to the tree pids
treePids = append(treePids,childLayer...)
// to analyze the next layer,set the child layer to be the new parent layer
parentLayer = childLayer
}
}
func contains(list []uint32,e uint32) bool {
for _,l := range list {
if l == e {
return true
}
}
return false
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。