Add standalone Go build alongside VSCode extension
Ports all five tools to a single 7.5 MB Windows exe with an embedded WebView2 window, file-based config, single-instance focus, and clean shutdown. Adds build.ps1 to build both targets from one command. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
68
standalone/single_instance.go
Normal file
68
standalone/single_instance.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func lockFilePath() string {
|
||||
return filepath.Join(appDir(), ".hpltoolbox.lock")
|
||||
}
|
||||
|
||||
// focusExistingInstance returns true if another instance was found and
|
||||
// successfully asked to focus its window. In that case the caller should exit.
|
||||
// Returns false if no live instance exists (and clears any stale lock).
|
||||
func focusExistingInstance() bool {
|
||||
data, err := os.ReadFile(lockFilePath())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
parts := strings.Split(strings.TrimSpace(string(data)), "\n")
|
||||
if len(parts) != 2 {
|
||||
_ = os.Remove(lockFilePath())
|
||||
return false
|
||||
}
|
||||
pid, errPid := strconv.Atoi(strings.TrimSpace(parts[0]))
|
||||
port, errPort := strconv.Atoi(strings.TrimSpace(parts[1]))
|
||||
if errPid != nil || errPort != nil {
|
||||
_ = os.Remove(lockFilePath())
|
||||
return false
|
||||
}
|
||||
|
||||
// Quick liveness check: PID must exist.
|
||||
if proc, err := os.FindProcess(pid); err != nil || proc == nil {
|
||||
_ = os.Remove(lockFilePath())
|
||||
return false
|
||||
}
|
||||
|
||||
// Ask the running instance to focus its window.
|
||||
client := &http.Client{Timeout: 1500 * time.Millisecond}
|
||||
url := fmt.Sprintf("http://127.0.0.1:%d/api/focus", port)
|
||||
resp, err := client.Post(url, "application/json", bytes.NewReader(nil))
|
||||
if err != nil {
|
||||
// Lock file is stale (process died but didn't clean up).
|
||||
_ = os.Remove(lockFilePath())
|
||||
return false
|
||||
}
|
||||
_ = resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
_ = os.Remove(lockFilePath())
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func writeLockFile(port int) error {
|
||||
content := fmt.Sprintf("%d\n%d\n", os.Getpid(), port)
|
||||
return os.WriteFile(lockFilePath(), []byte(content), 0644)
|
||||
}
|
||||
|
||||
func removeLockFile() {
|
||||
_ = os.Remove(lockFilePath())
|
||||
}
|
||||
Reference in New Issue
Block a user