//go:build windows package cursor import ( "os" "path/filepath" "strings" ) // maxScanDirs 限制驱动器扫描的目录总数,避免在超大盘上长时间阻塞。 const maxScanDirs = 8000 // skippedRootNames 是驱动器扫描时跳过的系统目录(大且不可能装 Cursor)。 var skippedRootNames = map[string]struct{}{ "windows": {}, "programdata": {}, "users": {}, "$recycle.bin": {}, "system volume information": {}, "recovery": {}, "perflogs": {}, "dumpstack.log.tmp": {}, "config.msi": {}, "intel": {}, "drivers": {}, "msocache": {}, } // scanDriveRootsForCursor 兜底扫描各固定驱动器: // 根目录与二级目录中查找名称含 cursor 且包含 Cursor.exe 的目录。 // 纯文件系统探测,不依赖注册表枚举或子进程(部分安全软件会拦截)。 func scanDriveRootsForCursor() string { visited := 0 for letter := 'C'; letter <= 'Z'; letter++ { drive := string(letter) + `:\` if _, err := os.Stat(drive); err != nil { continue } if dir := scanDirForCursor(drive, &visited); dir != "" { return dir } } return "" } // scanDirForCursor 在目录及其一级子目录中查找 Cursor 安装目录。 func scanDirForCursor(root string, visited *int) string { entries, err := os.ReadDir(root) if err != nil { return "" } var deferred []string for _, entry := range entries { if !entry.IsDir() { continue } name := entry.Name() if _, skip := skippedRootNames[strings.ToLower(name)]; skip { continue } *visited++ if *visited > maxScanDirs { return "" } full := filepath.Join(root, name) if strings.Contains(strings.ToLower(name), "cursor") { if isCursorInstallDir(full) { return full } continue } deferred = append(deferred, full) } // 二级目录:仅在一级目录名像程序目录时展开,控制扫描量。 for _, dir := range deferred { if !looksLikeProgramsDir(filepath.Base(dir)) { continue } if dir := scanDirForCursor(dir, visited); dir != "" { return dir } } return "" } // looksLikeProgramsDir 判断目录名是否像程序/工具安装根目录。 func looksLikeProgramsDir(name string) bool { lower := strings.ToLower(name) for _, keyword := range []string{"program", "app", "dev", "soft", "tool", "work", "bin"} { if strings.Contains(lower, keyword) { return true } } return false }