| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- //go:build windows
- package discovery
- import (
- "os/exec"
- "regexp"
- "sort"
- "strconv"
- "strings"
- )
- func findByPID() []int {
- var ports []int
- pidRegex := regexp.MustCompile(`(?i)(opencode|bun)`)
- tasklistOut, err := exec.Command("tasklist", "/FO", "CSV", "/NH").Output()
- if err != nil {
- return ports
- }
- var pids []int
- for _, line := range strings.Split(string(tasklistOut), "\n") {
- if pidRegex.MatchString(line) && !strings.Contains(line, "opencode-monitor") {
- fields := strings.Split(line, ",")
- if len(fields) >= 2 {
- pidStr := strings.Trim(fields[1], "\"")
- if pid, err := strconv.Atoi(pidStr); err == nil {
- pids = append(pids, pid)
- }
- }
- }
- }
- for _, pid := range pids {
- netstatOut, err := exec.Command("netstat", "-ano").Output()
- if err != nil {
- continue
- }
- for _, line := range strings.Split(string(netstatOut), "\n") {
- if strings.Contains(line, "LISTENING") {
- fields := strings.Fields(line)
- if len(fields) >= 5 {
- pidStr := fields[len(fields)-1]
- if netPid, err := strconv.Atoi(pidStr); err == nil && netPid == pid {
- addr := fields[1]
- if strings.Contains(addr, ":") {
- parts := strings.Split(addr, ":")
- if len(parts) >= 2 {
- if port, err := strconv.Atoi(parts[len(parts)-1]); err == nil {
- if !contains(ports, port) {
- ports = append(ports, port)
- }
- }
- }
- }
- }
- }
- }
- }
- }
- sort.Ints(ports)
- return ports
- }
- func findByCmdline() []int {
- var ports []int
- // 查找 opencode 进程
- wmicOut, err := exec.Command("wmic", "process", "where", "name like '%opencode%' and name not like '%opencode-monitor%'", "get", "commandline", "/FORMAT:LIST").Output()
- if err == nil {
- for _, line := range strings.Split(string(wmicOut), "\n") {
- if strings.Contains(line, "--port") {
- fields := strings.Fields(line)
- for i, f := range fields {
- if f == "--port" && i+1 < len(fields) {
- if port, err := strconv.Atoi(fields[i+1]); err == nil {
- if !contains(ports, port) {
- ports = append(ports, port)
- }
- }
- }
- }
- }
- }
- }
- // 查找 bun 进程运行的 opencode
- if len(ports) == 0 {
- bunOut, err := exec.Command("wmic", "process", "where", "name like '%bun%'", "get", "commandline", "/FORMAT:LIST").Output()
- if err == nil {
- for _, line := range strings.Split(string(bunOut), "\n") {
- if strings.Contains(line, "opencode") && strings.Contains(line, "--port") {
- fields := strings.Fields(line)
- for i, f := range fields {
- if f == "--port" && i+1 < len(fields) {
- if port, err := strconv.Atoi(fields[i+1]); err == nil {
- if !contains(ports, port) {
- ports = append(ports, port)
- }
- }
- }
- }
- }
- }
- }
- }
- // 使用 PowerShell 作为后备方案
- if len(ports) == 0 {
- powershellOut, err := exec.Command("powershell", "-Command", "Get-CimInstance Win32_Process | Where-Object {($_.Name -like '*opencode*' -and $_.Name -notlike '*opencode-monitor*') -or ($_.Name -like '*bun*' -and $_.CommandLine -like '*opencode*')} | Select-Object CommandLine").Output()
- if err == nil {
- for _, line := range strings.Split(string(powershellOut), "\n") {
- if strings.Contains(line, "--port") {
- fields := strings.Fields(line)
- for i, f := range fields {
- if f == "--port" && i+1 < len(fields) {
- if port, err := strconv.Atoi(fields[i+1]); err == nil {
- if !contains(ports, port) {
- ports = append(ports, port)
- }
- }
- }
- }
- }
- }
- }
- }
- sort.Ints(ports)
- return ports
- }
|