diff --git a/SCU SRCC Setup by SASWE.exe b/SRCC-b1.0-inst.exe similarity index 100% rename from SCU SRCC Setup by SASWE.exe rename to SRCC-b1.0-inst.exe diff --git a/logger.go b/logger.go index 6446cb4..df70787 100644 --- a/logger.go +++ b/logger.go @@ -4,10 +4,10 @@ // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND. // logger 模块:基于 zerolog 的日志初始化,支持控制台输出(可读格式)+ 文件输出(JSON 结构化)。 +// 日志目录优先级:exe 同目录 log/ → %APPDATA%/SRemoteConnectClient/log/ → 仅控制台输出。 package main import ( - "fmt" "io" "os" "path/filepath" @@ -19,42 +19,85 @@ import ( // log 包级全局日志实例,所有 .go 文件共用。 var log zerolog.Logger -// initLogger 初始化全局日志: -// - 日志文件存储在 srcc.exe 同目录的 log/ 下,按日期命名 -// - 控制台使用可读的 ConsoleWriter(带颜色) -// - 同时输出到控制台和文件 +// initLogger 初始化全局日志。 +// 尝试在 exe 目录下创建 log/,若无写权限(多用户安装场景)则回退到 %APPDATA%。 +// 日志按日期命名,控制台使用可读格式(带颜色),文件使用 JSON 结构化格式。 func initLogger() { - exePath, err := os.Executable() - if err != nil { - exePath, _ = os.Getwd() - } - exeDir := filepath.Dir(exePath) - - logDir := filepath.Join(exeDir, "log") - if err := os.MkdirAll(logDir, 0755); err != nil { - panic(fmt.Sprintf("无法创建日志目录: %v", err)) - } - - today := time.Now().Format("2006-01-02") - logFile := filepath.Join(logDir, today+".log") - - file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) - if err != nil { - panic(fmt.Sprintf("无法打开日志文件: %v", err)) - } - consoleWriter := zerolog.ConsoleWriter{ Out: os.Stdout, TimeFormat: "2006-01-02 15:04:05", NoColor: false, } - multi := io.MultiWriter(consoleWriter, file) + logFile := openLogFile() + if logFile == nil { + // 连 %APPDATA% 都写不了,仅控制台输出 + log = zerolog.New(consoleWriter). + With().Timestamp().Caller().Logger(). + Level(zerolog.DebugLevel) + return + } + multi := io.MultiWriter(consoleWriter, logFile) log = zerolog.New(multi). - With(). - Timestamp(). - Caller(). - Logger(). + With().Timestamp().Caller().Logger(). Level(zerolog.DebugLevel) } + +// openLogFile 按优先级尝试打开日志文件。 +// 返回 nil 表示无法创建日志文件,此时程序仅输出到控制台。 +func openLogFile() *os.File { + logDir, err := resolveLogDir() + if err != nil { + return nil + } + + today := time.Now().Format("2006-01-02") + logPath := filepath.Join(logDir, today+".log") + + f, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + return nil + } + return f +} + +// resolveLogDir 解析日志目录。 +// 优先使用 exe 同目录下的 log/;若不可写则使用 %APPDATA%/SRemoteConnectClient/log/。 +func resolveLogDir() (string, error) { + // 1. 尝试 exe 同目录 + exePath, _ := os.Executable() + if exePath != "" { + dir := filepath.Join(filepath.Dir(exePath), "log") + if err := os.MkdirAll(dir, 0755); err == nil { + // 验证确实可写 + testFile := filepath.Join(dir, ".write_test") + if f, err := os.Create(testFile); err == nil { + f.Close() + os.Remove(testFile) + return dir, nil + } + } + } + + // 2. 回退到 %APPDATA%/SRemoteConnectClient/log + appData := os.Getenv("APPDATA") + if appData == "" { + appData = os.Getenv("LOCALAPPDATA") + } + if appData != "" { + dir := filepath.Join(appData, "SRemoteConnectClient", "log") + if err := os.MkdirAll(dir, 0755); err == nil { + return dir, nil + } + } + + // 3. 最后尝试当前工作目录 + cwd, _ := os.Getwd() + dir := filepath.Join(cwd, "log") + if err := os.MkdirAll(dir, 0755); err == nil { + return dir, nil + } + + return "", os.ErrPermission +} diff --git a/srcc.exe b/srcc.exe index 0a83a9e..80e7159 100644 Binary files a/srcc.exe and b/srcc.exe differ