server_windows.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package lifecycle
  2. import (
  3. "context"
  4. "fmt"
  5. "os/exec"
  6. "syscall"
  7. "golang.org/x/sys/windows"
  8. )
  9. func getCmd(ctx context.Context, exePath string) *exec.Cmd {
  10. cmd := exec.CommandContext(ctx, exePath, "serve")
  11. cmd.SysProcAttr = &syscall.SysProcAttr{
  12. HideWindow: true,
  13. CreationFlags: windows.CREATE_NEW_PROCESS_GROUP,
  14. }
  15. return cmd
  16. }
  17. func terminate(cmd *exec.Cmd) error {
  18. dll, err := windows.LoadDLL("kernel32.dll")
  19. if err != nil {
  20. return err
  21. }
  22. //nolint:errcheck
  23. defer dll.Release()
  24. pid := cmd.Process.Pid
  25. f, err := dll.FindProc("AttachConsole")
  26. if err != nil {
  27. return err
  28. }
  29. r1, _, err := f.Call(uintptr(pid))
  30. if r1 == 0 && err != syscall.ERROR_ACCESS_DENIED {
  31. return err
  32. }
  33. f, err = dll.FindProc("SetConsoleCtrlHandler")
  34. if err != nil {
  35. return err
  36. }
  37. r1, _, err = f.Call(0, 1)
  38. if r1 == 0 {
  39. return err
  40. }
  41. f, err = dll.FindProc("GenerateConsoleCtrlEvent")
  42. if err != nil {
  43. return err
  44. }
  45. r1, _, err = f.Call(windows.CTRL_BREAK_EVENT, uintptr(pid))
  46. if r1 == 0 {
  47. return err
  48. }
  49. r1, _, err = f.Call(windows.CTRL_C_EVENT, uintptr(pid))
  50. if r1 == 0 {
  51. return err
  52. }
  53. return nil
  54. }
  55. const STILL_ACTIVE = 259
  56. func isProcessExited(pid int) (bool, error) {
  57. hProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(pid))
  58. if err != nil {
  59. return false, fmt.Errorf("failed to open process: %v", err)
  60. }
  61. //nolint:errcheck
  62. defer windows.CloseHandle(hProcess)
  63. var exitCode uint32
  64. err = windows.GetExitCodeProcess(hProcess, &exitCode)
  65. if err != nil {
  66. return false, fmt.Errorf("failed to get exit code: %v", err)
  67. }
  68. if exitCode == STILL_ACTIVE {
  69. return false, nil
  70. }
  71. return true, nil
  72. }