//go:build windows package main import ( "os/exec" "strconv" "strings" "syscall" "hamlog/internal/applog" wruntime "github.com/wailsapp/wails/v2/pkg/runtime" ) // hideConsole keeps a helper process from flashing a console window. OpsLog is // a GUI application, and every `tasklist`/`taskkill`/`powershell` it runs would // otherwise blink a black box in front of the operator mid-QSO. func hideConsole(cmd *exec.Cmd) { cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true, CreationFlags: 0x08000000} // CREATE_NO_WINDOW } // runningProcessNames returns the set of lowercase executable names currently // running, via the Windows `tasklist`. Best effort — on failure the set is // empty (we then just attempt to launch, which is acceptable). func runningProcessNames() map[string]bool { out := map[string]bool{} cmd := exec.Command("tasklist", "/FO", "CSV", "/NH") hideConsole(cmd) data, err := cmd.Output() if err != nil { applog.Printf("autostart: tasklist failed: %v", err) return out } for _, line := range strings.Split(string(data), "\n") { line = strings.TrimSpace(line) if line == "" { continue } // CSV row: "image.exe","PID",... — take the first quoted field. field := line if i := strings.Index(line[1:], "\""); i >= 0 && strings.HasPrefix(line, "\"") { field = line[1 : i+1] } field = strings.Trim(field, "\"") if field != "" { out[strings.ToLower(field)] = true } } return out } // closeProcess asks the process to close. `taskkill` without /F sends WM_CLOSE, // so WSJT-X and friends get to save their state instead of being shot. func closeProcess(pid int) ([]byte, error) { cmd := exec.Command("taskkill", "/PID", strconv.Itoa(pid)) hideConsole(cmd) return cmd.CombinedOutput() } // executableFilters is what the "choose a program" dialog offers. Windows knows // a program by its extension. func executableFilters() []wruntime.FileFilter { return []wruntime.FileFilter{ {DisplayName: "Programs (*.exe;*.bat;*.cmd)", Pattern: "*.exe;*.bat;*.cmd"}, {DisplayName: "All files (*.*)", Pattern: "*.*"}, } }