diff --git a/sysutil/process/procutil.go b/sysutil/process/procutil.go index 801657530..8da4db594 100644 --- a/sysutil/process/procutil.go +++ b/sysutil/process/procutil.go @@ -31,7 +31,7 @@ func ProcInfo(pid int) (*os.Process, error) { return os.FindProcess(pid) } -// PIDByName get PID by process name match +// PIDByName get PID by process name match(by pgrep) func PIDByName(keywords string) int { // pgrep keywords binFile := "pgrep" @@ -55,3 +55,17 @@ func KillByName(keywords string, sig syscall.Signal) error { } return errors.New("not found process pid of " + keywords) } + +// StopProcessOption stop process option +type StopProcessOption struct { + // Check if the process exists before stopping it + CheckExist bool + // Whether to force exit the process + ForceKill bool + // Whether to wait for the process to exit + WaitExit bool + // How long to wait for the process to exit + ExitTimeout int + // Signal to send to the process(non-win) + Signal syscall.Signal +} diff --git a/sysutil/process/procutil_nonwin.go b/sysutil/process/procutil_nonwin.go index 56ea110ba..24eaee92f 100644 --- a/sysutil/process/procutil_nonwin.go +++ b/sysutil/process/procutil_nonwin.go @@ -8,3 +8,19 @@ import "syscall" func Kill(pid int, signal syscall.Signal) error { return syscall.Kill(pid, signal) } + +// ExistsByName check process running by given name +func ExistsByName(name string, fuzzyMatch bool) bool { + return false // TODO +} + +// StopByName Stop process based on process name. +// +// return (exists, output, error). check error to see if the process exists +// +// Usage: +// +// StopByName("MyApp.exe") +func StopByName(name string, option ...*StopProcessOption) (bool, string, error) { + return false, "", nil // TODO +} diff --git a/sysutil/process/procutil_nonwin_test.go b/sysutil/process/procutil_nonwin_test.go new file mode 100644 index 000000000..f385b33f1 --- /dev/null +++ b/sysutil/process/procutil_nonwin_test.go @@ -0,0 +1,4 @@ +//go:build !windows +// +build !windows + +package process diff --git a/sysutil/process/procutil_windows.go b/sysutil/process/procutil_windows.go index c4731ea2c..dd4f188ab 100644 --- a/sysutil/process/procutil_windows.go +++ b/sysutil/process/procutil_windows.go @@ -1,8 +1,11 @@ package process import ( + "fmt" + "strings" "syscall" + "github.com/gookit/goutil/sysutil" "golang.org/x/sys/windows" ) @@ -41,3 +44,57 @@ func Exists(pid int) bool { } return true } + +// ExistsByName Determine whether a process exists based on its name(by tasklist) +// +// Usage: +// +// ExistsByName("MyApp.exe") +// // Fuzzy match by input name +// ExistsByName("MyApp", true) +func ExistsByName(name string, fuzzyMatch ...bool) bool { + // 按名称模糊匹配 + if len(fuzzyMatch) > 0 && fuzzyMatch[0] { + out, err := sysutil.ShellExec("tasklist | findstr \""+name+"\" /NH", "cmd") + if err != nil { + return false + } + return strings.Contains(out, name) + } + + out, err := sysutil.ExecCmd("tasklist", []string{"/FI", fmt.Sprintf("IMAGENAME eq %s", name), "/NH"}) + // out, err := sysutil.ShellExec("tasklist /FI \"IMAGENAME eq "+name+"\" /NH", "cmd") // shell执行有问题 + if err != nil { + return false + } + return strings.Contains(out, name) +} + +// StopByName Stop process based on process name(by taskkill). +// +// return (exists, output, error). check error to see if the process exists +// +// Usage: +// +// StopByName("MyApp.exe") +func StopByName(name string, option ...*StopProcessOption) (bool, string, error) { + opt := &StopProcessOption{} + if len(option) > 0 && option[0] != nil { + opt = option[0] + } + + // 1. 检查进程是否存在 + if opt.CheckExist { + if !ExistsByName(name) { + return false, "", nil + } + } + + // cmd: taskkill /IM name.exe /F + args := []string{"/IM", name} + if opt.ForceKill { + args = append(args, "/F") + } + out, err := sysutil.ExecCmd("taskkill", args) + return true, out, err +} diff --git a/sysutil/process/procutil_windows_test.go b/sysutil/process/procutil_windows_test.go new file mode 100644 index 000000000..10b738896 --- /dev/null +++ b/sysutil/process/procutil_windows_test.go @@ -0,0 +1,4 @@ +//go:build windows +// +build windows + +package process_test