server_windows.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package main
  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. defer dll.Release() // nolint: errcheck
  23. pid := cmd.Process.Pid
  24. f, err := dll.FindProc("AttachConsole")
  25. if err != nil {
  26. return err
  27. }
  28. r1, _, err := f.Call(uintptr(pid))
  29. if r1 == 0 && err != syscall.ERROR_ACCESS_DENIED {
  30. return err
  31. }
  32. f, err = dll.FindProc("SetConsoleCtrlHandler")
  33. if err != nil {
  34. return err
  35. }
  36. r1, _, err = f.Call(0, 1)
  37. if r1 == 0 {
  38. return err
  39. }
  40. f, err = dll.FindProc("GenerateConsoleCtrlEvent")
  41. if err != nil {
  42. return err
  43. }
  44. r1, _, err = f.Call(windows.CTRL_BREAK_EVENT, uintptr(pid))
  45. if r1 == 0 {
  46. return err
  47. }
  48. r1, _, err = f.Call(windows.CTRL_C_EVENT, uintptr(pid))
  49. if r1 == 0 {
  50. return err
  51. }
  52. return nil
  53. }
  54. const STILL_ACTIVE = 259
  55. func isProcessExited(pid int) (bool, error) {
  56. hProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(pid))
  57. if err != nil {
  58. return false, fmt.Errorf("failed to open process: %v", err)
  59. }
  60. defer windows.CloseHandle(hProcess) // nolint: errcheck
  61. var exitCode uint32
  62. err = windows.GetExitCodeProcess(hProcess, &exitCode)
  63. if err != nil {
  64. return false, fmt.Errorf("failed to get exit code: %v", err)
  65. }
  66. if exitCode == STILL_ACTIVE {
  67. return false, nil
  68. }
  69. return true, nil
  70. }