5013148ffe
User-reported install fixes: - Branding: every user-facing 'SSO Manager' string now says 'Theta Directory' (agent logs, CLI usage, agent.yml.example, installer wizard). - Wizard page: the URL/join-key text boxes were never shown. The layout used Surface.Width (0 at wizard init) instead of SurfaceWidth and combined WordWrap with AutoSize (mutually exclusive in VCL). Rewritten with the canonical Inno pattern (SurfaceWidth + ScaleY + explicit label height). - No console window after install: the tray and helper now build as GUI-subsystem binaries (-H=windowsgui) in build_all.sh and scripts/setup-build-env.ps1. The agent stays a console app for foreground debugging (as a service it never shows a console). - The daemon never came up after install: install-service now starts the service immediately, so the tray IPC socket exists right away and the tray connects instead of logging 'actively refused' until a reboot. Verified: go build/vet/test green; tray+helper PE subsystem = GUI (2), agent = console (3); installer compiles; tray runs silently.
95 lines
2.1 KiB
Go
95 lines
2.1 KiB
Go
//go:build windows
|
|
|
|
package main
|
|
|
|
// Service management CLI (theta-agent install-service / remove-service). The
|
|
// Inno installer also drives this rather than hand-rolling `sc create`.
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"golang.org/x/sys/windows/svc/mgr"
|
|
)
|
|
|
|
func handleServiceCommand(args []string) {
|
|
action := "install"
|
|
if len(args) > 0 {
|
|
action = args[0]
|
|
}
|
|
switch action {
|
|
case "install":
|
|
installService()
|
|
case "remove":
|
|
removeService()
|
|
default:
|
|
fmt.Fprintf(os.Stderr, "usage: theta-agent %s [install|remove]\n", action)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func installService() {
|
|
exe, err := os.Executable()
|
|
if err != nil {
|
|
logFatal("cannot resolve agent path: %v", err)
|
|
}
|
|
|
|
m, err := mgr.Connect()
|
|
if err != nil {
|
|
logFatal("cannot connect to service manager: %v", err)
|
|
}
|
|
defer m.Disconnect()
|
|
|
|
s, err := m.OpenService("theta-agent")
|
|
if err == nil {
|
|
s.Close()
|
|
fmt.Println("[+] theta-agent service already exists")
|
|
return
|
|
}
|
|
|
|
cfg := mgr.Config{
|
|
DisplayName: "Theta Agent",
|
|
Description: "Theta42 unified endpoint management agent (telemetry, remote ops, LDAP logon, WireGuard mesh)",
|
|
ServiceStartName: "LocalSystem",
|
|
StartType: mgr.StartAutomatic,
|
|
}
|
|
s, err = m.CreateService("theta-agent", exe, cfg, "is", "auto")
|
|
if err != nil {
|
|
logFatal("cannot create service: %v", err)
|
|
}
|
|
defer s.Close()
|
|
|
|
// Start it immediately so the daemon binds the tray IPC socket and the
|
|
// credential provider is live without waiting for a reboot.
|
|
if err := s.Start(); err != nil {
|
|
logFatal("cannot start service: %v", err)
|
|
}
|
|
fmt.Printf("[+] Registered and started theta-agent service (%s)\n", filepath.Base(exe))
|
|
}
|
|
|
|
func removeService() {
|
|
m, err := mgr.Connect()
|
|
if err != nil {
|
|
logFatal("cannot connect to service manager: %v", err)
|
|
}
|
|
defer m.Disconnect()
|
|
|
|
s, err := m.OpenService("theta-agent")
|
|
if err != nil {
|
|
fmt.Println("[!] theta-agent service not found")
|
|
return
|
|
}
|
|
defer s.Close()
|
|
|
|
if err := s.Delete(); err != nil {
|
|
logFatal("cannot delete service: %v", err)
|
|
}
|
|
fmt.Println("[+] Removed theta-agent service")
|
|
}
|
|
|
|
func logFatal(format string, args ...interface{}) {
|
|
fmt.Fprintf(os.Stderr, "[!] "+format+"\n", args...)
|
|
os.Exit(1)
|
|
}
|