package main import ( "fmt" "net" "os" "strings" "time" ) const appVersion = "2.0.0" const mutexName = "Global\\DeepSeekTraySingleton" func main() { args := os.Args[1:] cfg := loadConfig() log := NewLogger() defer log.Close() log.Printf("=== deepseek-tray %s 启动 args=%v ===", appVersion, args) if len(args) > 0 { switch strings.ToLower(strings.TrimLeft(args[0], "-/")) { case "version": attachConsole() fmt.Println(appVersion) return case "status": attachConsole() printStatus(cfg, log) return case "daemon": runDaemon(cfg, log) return } } inst, ok := acquireSingleInstance(mutexName) if !ok { attachConsole() fmt.Println("deepseek-tray 已在运行(托盘或守护进程)") return } defer inst.release() runTray(cfg, log) } // runDaemon 无 UI 守护模式(适合 NSSM 注册为 Windows 服务)。 func runDaemon(cfg *Config, log *Logger) { log.Printf("以守护模式启动(无托盘)") inst, ok := acquireSingleInstance(mutexName) if !ok { log.Printf("已有实例在运行,退出") return } defer inst.release() sup := NewSupervisor(cfg, log) sup.Start() if cfg.AutoUpdate { sup.startAutoUpdate() } select {} } // printStatus 命令行状态查询。 func printStatus(cfg *Config, log *Logger) { sup := NewSupervisor(cfg, log) version := sup.installedVersion() if version == "" { version = "未知(未找到 dsh)" } url := fmt.Sprintf("http://%s:%d", cfg.WebHost, cfg.WebPort) fmt.Printf("deepseek-tray %s\n", appVersion) fmt.Printf("DSH 版本 : %s\n", version) fmt.Printf("Web 地址 : %s\n", url) fmt.Printf("端口监听 : %v\n", portOpen(cfg.WebHost, cfg.WebPort)) fmt.Printf("开机自启 : %v\n", isAutoStartEnabled()) fmt.Printf("定期自动更新: %v(间隔 %d 小时)\n", cfg.AutoUpdate, cfg.UpdateIntervalH) fmt.Printf("配置文件 : %s\n", configPath()) fmt.Printf("日志文件 : %s\n", log.Path()) } func portOpen(host string, port int) bool { if host == "" { host = "127.0.0.1" } conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), 1500*time.Millisecond) if err != nil { return false } _ = conn.Close() return true }