简体   繁体   English

golang如何通过进程名称获取进程ID?

[英]How golang to get process id by process name?

I want to get the process id by the process name in windows environment?我想在windows环境下通过进程名获取进程id?

I find golang only has the api os.FindProcess(id) ,but no by name.我发现 golang 只有 api os.FindProcess(id) ,但没有名字。

You can list all the processes and match them with the name you want to find, by using the updated sys call package, https://godoc.org/golang.org/x/sys , it has most of the windows api.您可以列出所有进程并将它们与您要查找的名称进行匹配,通过使用更新的 sys 调用包https://godoc.org/golang.org/x/sys ,它具有大部分 windows api。

func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error)
func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error)

also see the msdn docs: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684834(v=vs.85).aspx另请参阅 msdn 文档: https ://msdn.microsoft.com/en-us/library/windows/desktop/ms684834( v= vs.85).aspx

I had to struggle with this too, and found the way to the solution not very straightforward, because… WinApi :)我也不得不为此挣扎,并发现解决方案的方法不是很简单,因为... WinApi :)

In the end you have to create a snapshot of the current windows process list using CreateToolhelp32Snapshot .最后,您必须使用CreateToolhelp32Snapshot创建当前 Windows 进程列表的CreateToolhelp32Snapshot Then you get the first process in the snapshot with Process32First .然后您使用Process32First获得快照中的第一个进程。 After that keep iterating over the list with Process32Next , until you get the ERROR_NO_MORE_FILES error.之后继续使用Process32Next遍历列表,直到出现ERROR_NO_MORE_FILES错误。 Only then you have the whole process list.只有这样,您才能拥有整个流程列表。

See how2readwindowsprocesses for a working example.有关工作示例,请参阅how2readwindowsprocesses

Here is the gist:这是要点:

const TH32CS_SNAPPROCESS = 0x00000002

type WindowsProcess struct {
    ProcessID       int
    ParentProcessID int
    Exe             string
}

func processes() ([]WindowsProcess, error) {
    handle, err := windows.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    if err != nil {
        return nil, err
    }
    defer windows.CloseHandle(handle)

    var entry windows.ProcessEntry32
    entry.Size = uint32(unsafe.Sizeof(entry))
    // get the first process
    err = windows.Process32First(handle, &entry)
    if err != nil {
        return nil, err
    }

    results := make([]WindowsProcess, 0, 50)
    for {
        results = append(results, newWindowsProcess(&entry))

        err = windows.Process32Next(handle, &entry)
        if err != nil {
            // windows sends ERROR_NO_MORE_FILES on last process
            if err == syscall.ERROR_NO_MORE_FILES {
                return results, nil
            }
            return nil, err
        }
    }
}

func findProcessByName(processes []WindowsProcess, name string) *WindowsProcess {
    for _, p := range processes {
        if strings.ToLower(p.Exe) == strings.ToLower(name) {
            return &p
        }
    }
    return nil
}

func newWindowsProcess(e *windows.ProcessEntry32) WindowsProcess {
    // Find when the string ends for decoding
    end := 0
    for {
        if e.ExeFile[end] == 0 {
            break
        }
        end++
    }

    return WindowsProcess{
        ProcessID:       int(e.ProcessID),
        ParentProcessID: int(e.ParentProcessID),
        Exe:             syscall.UTF16ToString(e.ExeFile[:end]),
    }
}
const TH32CS_SNAPPROCESS = 0x00000002

type WindowsProcess struct {
    ProcessID       int
    ParentProcessID int
    Exe             string
}

func newWindowsProcess(e *syscall.ProcessEntry32) WindowsProcess {
    // Find when the string ends for decoding
    end := 0
    for {
        if e.ExeFile[end] == 0 {
            break
        }
        end++
    }

    return WindowsProcess{
        ProcessID:       int(e.ProcessID),
        ParentProcessID: int(e.ParentProcessID),
        Exe:             syscall.UTF16ToString(e.ExeFile[:end]),
    }
}

func processes() ([]WindowsProcess, error) {
    handle, err := syscall.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    if err != nil {
        return nil, err
    }
    defer syscall.CloseHandle(handle)

    var entry syscall.ProcessEntry32
    entry.Size = uint32(unsafe.Sizeof(entry))
    // get the first process
    err = syscall.Process32First(handle, &entry)
    if err != nil {
        return nil, err
    }

    results := make([]WindowsProcess, 0, 50)
    for {
        results = append(results, newWindowsProcess(&entry))

        err = syscall.Process32Next(handle, &entry)
        if err != nil {
            // windows sends ERROR_NO_MORE_FILES on last process
            if err == syscall.ERROR_NO_MORE_FILES {
                return results, nil
            }
            return nil, err
        }
    }
}

func findProcessByName(processes []WindowsProcess, name string) *WindowsProcess {
    for _, p := range processes {
        if bytes.Contains([]byte(strings.ToUpper(p.Exe)),     []byte(strings.ToUpper(name))) {
            return &p
        }
    }
    return nil
}

This seems to do it:这似乎做到了:

package main

import (
   "fmt"
   "golang.org/x/sys/windows"
)

// unsafe.Sizeof(windows.ProcessEntry32{})
const processEntrySize = 568

func processID(name string) (uint32, error) {
   h, e := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)
   if e != nil { return 0, e }
   p := windows.ProcessEntry32{Size: processEntrySize}
   for {
      e := windows.Process32Next(h, &p)
      if e != nil { return 0, e }
      if windows.UTF16ToString(p.ExeFile[:]) == name {
         return p.ProcessID, nil
      }
   }
   return 0, fmt.Errorf("%q not found", name)
}

func main() {
   n, e := processID("WindowsTerminal.exe")
   if e != nil {
      panic(e)
   }
   println(n)
}

https://pkg.go.dev/golang.org/x/sys/windows#CreateToolhelp32Snapshot https://pkg.go.dev/golang.org/x/sys/windows#CreateToolhelp32Snapshot

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM