process_windows.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. package process
  2. import (
  3. "os"
  4. "golang.org/x/sys/windows"
  5. )
  6. // Alive returns true if process with a given pid is running.
  7. func Alive(pid int) bool {
  8. h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
  9. if err != nil {
  10. return false
  11. }
  12. var c uint32
  13. err = windows.GetExitCodeProcess(h, &c)
  14. _ = windows.CloseHandle(h)
  15. if err != nil {
  16. // From the GetExitCodeProcess function (processthreadsapi.h) API docs:
  17. // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess
  18. //
  19. // The GetExitCodeProcess function returns a valid error code defined by the
  20. // application only after the thread terminates. Therefore, an application should
  21. // not use STILL_ACTIVE (259) as an error code (STILL_ACTIVE is a macro for
  22. // STATUS_PENDING (minwinbase.h)). If a thread returns STILL_ACTIVE (259) as
  23. // an error code, then applications that test for that value could interpret it
  24. // to mean that the thread is still running, and continue to test for the
  25. // completion of the thread after the thread has terminated, which could put
  26. // the application into an infinite loop.
  27. return c == uint32(windows.STATUS_PENDING)
  28. }
  29. return true
  30. }
  31. // Kill force-stops a process.
  32. func Kill(pid int) error {
  33. p, err := os.FindProcess(pid)
  34. if err == nil {
  35. err = p.Kill()
  36. if err != nil && err != os.ErrProcessDone {
  37. return err
  38. }
  39. }
  40. return nil
  41. }