//go:build windows package copilot import ( "bytes" "errors" "fmt" "os" "os/exec" "strconv" "strings" "syscall" ) func prepareCmdForKill(cmd *exec.Cmd) { if cmd == nil { return } if cmd.SysProcAttr == nil { cmd.SysProcAttr = &syscall.SysProcAttr{} } cmd.SysProcAttr.CreationFlags |= syscall.CREATE_NEW_PROCESS_GROUP } func terminateCmd(cmd *exec.Cmd) { if cmd == nil || cmd.Process == nil { return } _ = cmd.Process.Signal(os.Interrupt) } func forceKillCmd(cmd *exec.Cmd) error { if cmd == nil || cmd.Process == nil { return nil } killCmd := exec.Command("taskkill", "/T", "/F", "/PID", strconv.Itoa(cmd.Process.Pid)) output, err := killCmd.CombinedOutput() if err == nil { return nil } if bytes.Contains(bytes.ToLower(output), []byte("there is no running instance")) { return nil } if bytes.Contains(bytes.ToLower(output), []byte("not found")) { return nil } if killErr := cmd.Process.Kill(); killErr == nil || errors.Is(killErr, os.ErrProcessDone) { return nil } else { return fmt.Errorf("taskkill failed: %w: %s; process kill fallback failed: %w", err, processKillOutput(output), killErr) } } func processKillOutput(output []byte) string { trimmed := strings.TrimSpace(string(output)) if trimmed == "" { return "(empty output)" } return trimmed }