[process][windows] Use win32 API in process.Children() instead of slow WMI call

The CreateToolhelp32Snapshot+Process32First+Process32Next combo already
iterates over all processes, so it would be inefficient to enumerate all
processes with process.Processes() and then calling p.Ppid() on each of
them: we just use this combo to get all processes and their ppid in a
single iteration.

This is faster by a factor of 25 compared to the previous WMI call.
pull/609/head
Lomanic 7 years ago
parent 48177ef5f8
commit 6b539051d2

@ -250,6 +250,7 @@ func (p *Process) Status() (string, error) {
func (p *Process) StatusWithContext(ctx context.Context) (string, error) { func (p *Process) StatusWithContext(ctx context.Context) (string, error) {
return "", common.ErrNotImplementedError return "", common.ErrNotImplementedError
} }
func (p *Process) Username() (string, error) { func (p *Process) Username() (string, error) {
return p.UsernameWithContext(context.Background()) return p.UsernameWithContext(context.Background())
} }
@ -456,22 +457,33 @@ func (p *Process) Children() ([]*Process, error) {
} }
func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) { func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
var dst []Win32_Process out := []*Process{}
query := wmi.CreateQuery(&dst, fmt.Sprintf("Where ParentProcessId = %d", p.Pid)) snap := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPPROCESS, uint32(0))
err := common.WMIQueryWithContext(ctx, query, &dst) if snap == 0 {
if err != nil { return out, windows.GetLastError()
return nil, err }
defer w32.CloseHandle(snap)
var pe32 w32.PROCESSENTRY32
pe32.DwSize = uint32(unsafe.Sizeof(pe32))
if w32.Process32First(snap, &pe32) == false {
return out, windows.GetLastError()
} }
out := []*Process{} if pe32.Th32ParentProcessID == uint32(p.Pid) {
for _, proc := range dst { p, err := NewProcess(int32(pe32.Th32ProcessID))
p, err := NewProcess(int32(proc.ProcessID)) if err == nil {
if err != nil { out = append(out, p)
continue
} }
out = append(out, p)
} }
for w32.Process32Next(snap, &pe32) {
if pe32.Th32ParentProcessID == uint32(p.Pid) {
p, err := NewProcess(int32(pe32.Th32ProcessID))
if err == nil {
out = append(out, p)
}
}
}
return out, nil return out, nil
} }

Loading…
Cancel
Save