From 139ba0b6386a934e05cab8ae83312b5d198013ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=85=8E=E9=A5=BC=E6=9E=9C=E5=AD=90=E5=8D=B7=E9=B2=A8?= =?UTF-8?q?=E9=B1=BC=E8=BE=A3=E6=A4=92?= Date: Sun, 21 Dec 2025 01:41:26 +0800 Subject: [PATCH] =?UTF-8?q?chore(scripts):=20=E5=88=A0=E9=99=A4=20Cursor?= =?UTF-8?q?=20=E5=85=8D=E8=B4=B9=E8=AF=95=E7=94=A8=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了 macOS 平台下用于重置 Cursor 编辑器免费试用期的 shell 脚本 - 该脚本包含修改应用程序文件、重置配置及权限修复等功能 - 脚本文件路径为 scripts/run/cursor_mac_free_trial_reset.sh - 此变更不影响其他平台或功能的正常使用 --- scripts/run/cursor_mac_free_trial_reset.sh | 1401 -------------------- scripts/run/cursor_mac_id_modifier_new.sh | 688 ---------- scripts/run/cursor_win_id_modifier_old.ps1 | 607 --------- 3 files changed, 2696 deletions(-) delete mode 100644 scripts/run/cursor_mac_free_trial_reset.sh delete mode 100644 scripts/run/cursor_mac_id_modifier_new.sh delete mode 100644 scripts/run/cursor_win_id_modifier_old.ps1 diff --git a/scripts/run/cursor_mac_free_trial_reset.sh b/scripts/run/cursor_mac_free_trial_reset.sh deleted file mode 100644 index 13f2a5b..0000000 --- a/scripts/run/cursor_mac_free_trial_reset.sh +++ /dev/null @@ -1,1401 +0,0 @@ -#!/bin/bash - -# 设置错误处理 -set -e - -# 定义日志文件路径 -LOG_FILE="/tmp/cursor_free_trial_reset.log" - -# 初始化日志文件 -initialize_log() { - echo "========== Cursor Free Trial Reset Tool Log Start $(date) ==========" > "$LOG_FILE" - chmod 644 "$LOG_FILE" -} - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# 日志函数 - 同时输出到终端和日志文件 -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" - echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE" -} - -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" - echo "[WARN] $(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" - echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE" -} - -log_debug() { - echo -e "${BLUE}[DEBUG]${NC} $1" - echo "[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FILE" -} - -# 记录命令输出到日志文件 -log_cmd_output() { - local cmd="$1" - local msg="$2" - echo "[CMD] $(date '+%Y-%m-%d %H:%M:%S') 执行命令: $cmd" >> "$LOG_FILE" - echo "[CMD] $msg:" >> "$LOG_FILE" - eval "$cmd" 2>&1 | tee -a "$LOG_FILE" - echo "" >> "$LOG_FILE" -} - -# 获取当前用户 -get_current_user() { - if [ "$EUID" -eq 0 ]; then - echo "$SUDO_USER" - else - echo "$USER" - fi -} - -CURRENT_USER=$(get_current_user) -if [ -z "$CURRENT_USER" ]; then - log_error "无法获取用户名" - exit 1 -fi - -# 定义配置文件路径 -STORAGE_FILE="$HOME/Library/Application Support/Cursor/User/globalStorage/storage.json" -BACKUP_DIR="$HOME/Library/Application Support/Cursor/User/globalStorage/backups" - -# 定义 Cursor 应用程序路径 -CURSOR_APP_PATH="/Applications/Cursor.app" - -# 🚀 新增 Cursor 防掉试用Pro删除文件夹功能 -remove_cursor_trial_folders() { - echo - log_info "🎯 [核心功能] 正在执行 Cursor 防掉试用Pro删除文件夹..." - log_info "📋 [说明] 此功能将删除指定的Cursor相关文件夹以重置试用状态" - echo - - # 定义需要删除的文件夹路径 - local folders_to_delete=( - "$HOME/Library/Application Support/Cursor" - "$HOME/.cursor" - ) - - log_info "📂 [检测] 将检查以下文件夹:" - for folder in "${folders_to_delete[@]}"; do - echo " 📁 $folder" - done - echo - - local deleted_count=0 - local skipped_count=0 - local error_count=0 - - # 删除指定文件夹 - for folder in "${folders_to_delete[@]}"; do - log_debug "🔍 [检查] 检查文件夹: $folder" - - if [ -d "$folder" ]; then - log_warn "⚠️ [警告] 发现文件夹存在,正在删除..." - if rm -rf "$folder"; then - log_info "✅ [成功] 已删除文件夹: $folder" - ((deleted_count++)) - else - log_error "❌ [错误] 删除文件夹失败: $folder" - ((error_count++)) - fi - else - log_warn "⏭️ [跳过] 文件夹不存在: $folder" - ((skipped_count++)) - fi - echo - done - - # 🔧 重要:深度修复权限问题 - log_info "🔧 [深度修复] 正在进行全面的权限修复..." - local cursor_support_dir="$HOME/Library/Application Support/Cursor" - local cursor_home_dir="$HOME/.cursor" - - # 创建完整的目录结构(包括Cursor可能需要的所有子目录) - local directories=( - "$cursor_support_dir" - "$cursor_support_dir/User" - "$cursor_support_dir/User/globalStorage" - "$cursor_support_dir/User/workspaceStorage" - "$cursor_support_dir/User/History" - "$cursor_support_dir/logs" - "$cursor_support_dir/CachedData" - "$cursor_support_dir/CachedExtensions" - "$cursor_support_dir/CachedExtensionVSIXs" - "$cursor_home_dir" - "$cursor_home_dir/extensions" - ) - - log_info "📁 [创建] 创建完整的目录结构..." - for dir in "${directories[@]}"; do - if mkdir -p "$dir" 2>/dev/null; then - log_debug "✅ 创建目录: $dir" - else - log_warn "⚠️ 创建目录失败: $dir" - fi - done - - # 设置递归权限(确保所有子目录都有正确权限) - log_info "🔐 [权限] 设置递归权限..." - chmod -R 755 "$cursor_support_dir" 2>/dev/null || true - chmod -R 755 "$cursor_home_dir" 2>/dev/null || true - - # 特别处理:确保当前用户拥有这些目录 - log_info "👤 [所有权] 确保目录所有权正确..." - chown -R "$(whoami)" "$cursor_support_dir" 2>/dev/null || true - chown -R "$(whoami)" "$cursor_home_dir" 2>/dev/null || true - - # 验证权限设置 - log_info "🔍 [验证] 验证权限设置..." - if [ -w "$cursor_support_dir" ] && [ -w "$cursor_home_dir" ]; then - log_info "✅ [成功] 权限验证通过" - else - log_warn "⚠️ [警告] 权限验证失败,可能仍存在问题" - fi - - # 🔍 权限诊断 - log_info "🔍 [诊断] 执行权限诊断..." - echo " 📁 目录权限检查:" - for dir in "${directories[@]}"; do - if [ -d "$dir" ]; then - local perms=$(ls -ld "$dir" | awk '{print $1, $3, $4}') - echo " ✅ $dir: $perms" - else - echo " ❌ $dir: 不存在" - fi - done - - # 🔍 权限诊断 - log_info "🔍 [诊断] 执行权限诊断..." - echo " 📁 目录权限检查:" - for dir in "${directories[@]}"; do - if [ -d "$dir" ]; then - local perms=$(ls -ld "$dir" | awk '{print $1, $3, $4}') - echo " ✅ $dir: $perms" - else - echo " ❌ $dir: 不存在" - fi - done - - log_info "✅ [完成] 深度权限修复完成" - echo - - # 显示操作统计 - log_info "📊 [统计] 操作完成统计:" - echo " ✅ 成功删除: $deleted_count 个文件夹" - echo " ⏭️ 跳过处理: $skipped_count 个文件夹" - echo " ❌ 删除失败: $error_count 个文件夹" - echo - - if [ $deleted_count -gt 0 ]; then - log_info "🎉 [完成] Cursor 防掉试用Pro文件夹删除完成!" - else - log_warn "🤔 [提示] 未找到需要删除的文件夹,可能已经清理过了" - fi - echo -} - -# 🔄 重启Cursor并等待配置文件生成 -restart_cursor_and_wait() { - echo - log_info "🔄 [重启] 正在重启Cursor以重新生成配置文件..." - - if [ -z "$CURSOR_PROCESS_PATH" ]; then - log_error "❌ [错误] 未找到Cursor进程信息,无法重启" - return 1 - fi - - log_info "📍 [路径] 使用路径: $CURSOR_PROCESS_PATH" - - if [ ! -f "$CURSOR_PROCESS_PATH" ]; then - log_error "❌ [错误] Cursor可执行文件不存在: $CURSOR_PROCESS_PATH" - return 1 - fi - - # 🔧 启动前最后一次权限确认 - log_info "🔧 [最终权限] 启动前最后一次权限确认..." - local cursor_support_dir="$HOME/Library/Application Support/Cursor" - local cursor_home_dir="$HOME/.cursor" - - # 再次确认完整目录结构存在 - local directories=( - "$cursor_support_dir" - "$cursor_support_dir/User" - "$cursor_support_dir/User/globalStorage" - "$cursor_support_dir/logs" - "$cursor_support_dir/CachedData" - "$cursor_home_dir" - "$cursor_home_dir/extensions" - ) - - for dir in "${directories[@]}"; do - mkdir -p "$dir" 2>/dev/null || true - done - - # 设置强制权限 - chmod -R 755 "$cursor_support_dir" 2>/dev/null || true - chmod -R 755 "$cursor_home_dir" 2>/dev/null || true - chown -R "$(whoami)" "$cursor_support_dir" 2>/dev/null || true - chown -R "$(whoami)" "$cursor_home_dir" 2>/dev/null || true - - # 启动Cursor - log_info "🚀 [启动] 正在启动Cursor..." - "$CURSOR_PROCESS_PATH" > /dev/null 2>&1 & - CURSOR_PID=$! - - log_info "⏳ [等待] 等待15秒让Cursor完全启动并生成配置文件..." - sleep 15 - - # 检查配置文件是否生成 - local config_path="$HOME/Library/Application Support/Cursor/User/globalStorage/storage.json" - local max_wait=30 - local waited=0 - - while [ ! -f "$config_path" ] && [ $waited -lt $max_wait ]; do - log_info "⏳ [等待] 等待配置文件生成... ($waited/$max_wait 秒)" - sleep 1 - waited=$((waited + 1)) - done - - if [ -f "$config_path" ]; then - log_info "✅ [成功] 配置文件已生成: $config_path" - else - log_warn "⚠️ [警告] 配置文件未在预期时间内生成,继续执行..." - fi - - # 强制关闭Cursor - log_info "🔄 [关闭] 正在关闭Cursor以进行配置修改..." - if [ ! -z "$CURSOR_PID" ]; then - kill $CURSOR_PID 2>/dev/null || true - fi - - # 确保所有Cursor进程都关闭 - pkill -f "Cursor" 2>/dev/null || true - - log_info "✅ [完成] Cursor重启流程完成" - return 0 -} - -# 🛠️ 修改机器码配置 -modify_machine_code_config() { - echo - log_info "🛠️ [配置] 正在修改机器码配置..." - - local config_path="$HOME/Library/Application Support/Cursor/User/globalStorage/storage.json" - - if [ ! -f "$config_path" ]; then - log_error "❌ [错误] 配置文件不存在: $config_path" - log_info "💡 [提示] 请手动启动Cursor一次,然后重新运行此脚本" - return 1 - fi - - # 生成新的ID - local MAC_MACHINE_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') - local UUID=$(uuidgen | tr '[:upper:]' '[:lower:]') - local MACHINE_ID="auth0|user_$(openssl rand -hex 32)" - local SQM_ID="{$(uuidgen | tr '[:lower:]' '[:upper:]')}" - - log_info "🔧 [生成] 已生成新的设备标识符" - - # 备份原始配置 - local backup_dir="$HOME/Library/Application Support/Cursor/User/globalStorage/backups" - mkdir -p "$backup_dir" - - local backup_name="storage.json.backup_$(date +%Y%m%d_%H%M%S)" - cp "$config_path" "$backup_dir/$backup_name" - log_info "💾 [备份] 已备份原配置: $backup_name" - - # 使用Python修改JSON配置(更可靠) - python3 -c " -import json -import sys - -try: - with open('$config_path', 'r', encoding='utf-8') as f: - config = json.load(f) - - config['telemetry.machineId'] = '$MACHINE_ID' - config['telemetry.macMachineId'] = '$MAC_MACHINE_ID' - config['telemetry.devDeviceId'] = '$UUID' - config['telemetry.sqmId'] = '$SQM_ID' - - with open('$config_path', 'w', encoding='utf-8') as f: - json.dump(config, f, indent=2, ensure_ascii=False) - - print('SUCCESS') -except Exception as e: - print(f'ERROR: {e}') - sys.exit(1) -" 2>/dev/null - - if [ $? -eq 0 ]; then - log_info "✅ [成功] 机器码配置修改完成" - log_info "📋 [详情] 已更新以下标识符:" - echo " 🔹 machineId: ${MACHINE_ID:0:20}..." - echo " 🔹 macMachineId: $MAC_MACHINE_ID" - echo " 🔹 devDeviceId: $UUID" - echo " 🔹 sqmId: $SQM_ID" - return 0 - else - log_error "❌ [错误] 修改配置失败" - return 1 - fi -} - -# 检查权限 -check_permissions() { - if [ "$EUID" -ne 0 ]; then - log_error "请使用 sudo 运行此脚本" - echo "示例: sudo $0" - exit 1 - fi -} - -# 检查并关闭 Cursor 进程(保存进程信息) -check_and_kill_cursor() { - log_info "🔍 [检查] 检查 Cursor 进程..." - - local attempt=1 - local max_attempts=5 - - # 💾 保存Cursor进程路径 - CURSOR_PROCESS_PATH="/Applications/Cursor.app/Contents/MacOS/Cursor" - - # 函数:获取进程详细信息 - get_process_details() { - local process_name="$1" - log_debug "正在获取 $process_name 进程详细信息:" - ps aux | grep -i "/Applications/Cursor.app" | grep -v grep - } - - while [ $attempt -le $max_attempts ]; do - # 使用更精确的匹配来获取 Cursor 进程 - CURSOR_PIDS=$(ps aux | grep -i "/Applications/Cursor.app" | grep -v grep | awk '{print $2}') - - if [ -z "$CURSOR_PIDS" ]; then - log_info "💡 [提示] 未发现运行中的 Cursor 进程" - # 确认Cursor应用路径存在 - if [ -f "$CURSOR_PROCESS_PATH" ]; then - log_info "💾 [保存] 已保存Cursor路径: $CURSOR_PROCESS_PATH" - else - log_warn "⚠️ [警告] 未找到Cursor应用,请确认已安装" - fi - return 0 - fi - - log_warn "⚠️ [警告] 发现 Cursor 进程正在运行" - # 💾 保存进程信息 - log_info "💾 [保存] 已保存Cursor路径: $CURSOR_PROCESS_PATH" - get_process_details "cursor" - - log_warn "🔄 [操作] 尝试关闭 Cursor 进程..." - - if [ $attempt -eq $max_attempts ]; then - log_warn "💥 [强制] 尝试强制终止进程..." - kill -9 $CURSOR_PIDS 2>/dev/null || true - else - kill $CURSOR_PIDS 2>/dev/null || true - fi - - sleep 1 - - # 同样使用更精确的匹配来检查进程是否还在运行 - if ! ps aux | grep -i "/Applications/Cursor.app" | grep -v grep > /dev/null; then - log_info "✅ [成功] Cursor 进程已成功关闭" - return 0 - fi - - log_warn "⏳ [等待] 等待进程关闭,尝试 $attempt/$max_attempts..." - ((attempt++)) - done - - log_error "❌ [错误] 在 $max_attempts 次尝试后仍无法关闭 Cursor 进程" - get_process_details "cursor" - log_error "💥 [错误] 请手动关闭进程后重试" - exit 1 -} - -# 备份配置文件 -backup_config() { - if [ ! -f "$STORAGE_FILE" ]; then - log_warn "配置文件不存在,跳过备份" - return 0 - fi - - mkdir -p "$BACKUP_DIR" - local backup_file="$BACKUP_DIR/storage.json.backup_$(date +%Y%m%d_%H%M%S)" - - if cp "$STORAGE_FILE" "$backup_file"; then - chmod 644 "$backup_file" - chown "$CURRENT_USER" "$backup_file" - log_info "配置已备份到: $backup_file" - else - log_error "备份失败" - exit 1 - fi -} - -# 生成随机 ID -generate_random_id() { - # 生成32字节(64个十六进制字符)的随机数 - openssl rand -hex 32 -} - -# 生成随机 UUID -generate_uuid() { - uuidgen | tr '[:upper:]' '[:lower:]' -} - -# 修改现有文件 -modify_or_add_config() { - local key="$1" - local value="$2" - local file="$3" - - if [ ! -f "$file" ]; then - log_error "文件不存在: $file" - return 1 - fi - - # 确保文件可写 - chmod 644 "$file" || { - log_error "无法修改文件权限: $file" - return 1 - } - - # 创建临时文件 - local temp_file=$(mktemp) - - # 检查key是否存在 - if grep -q "\"$key\":" "$file"; then - # key存在,执行替换 - sed "s/\"$key\":[[:space:]]*\"[^\"]*\"/\"$key\": \"$value\"/" "$file" > "$temp_file" || { - log_error "修改配置失败: $key" - rm -f "$temp_file" - return 1 - } - else - # key不存在,添加新的key-value对 - sed "s/}$/,\n \"$key\": \"$value\"\n}/" "$file" > "$temp_file" || { - log_error "添加配置失败: $key" - rm -f "$temp_file" - return 1 - } - fi - - # 检查临时文件是否为空 - if [ ! -s "$temp_file" ]; then - log_error "生成的临时文件为空" - rm -f "$temp_file" - return 1 - fi - - # 使用 cat 替换原文件内容 - cat "$temp_file" > "$file" || { - log_error "无法写入文件: $file" - rm -f "$temp_file" - return 1 - } - - rm -f "$temp_file" - - # 恢复文件权限 - chmod 444 "$file" - - return 0 -} - -# 生成新的配置 -generate_new_config() { - echo - log_warn "机器码处理" - - # 默认不重置机器码 - reset_choice=0 - - # 记录日志以便调试 - echo "[INPUT_DEBUG] 机器码重置选项: 不重置 (默认)" >> "$LOG_FILE" - - # 处理 - 默认为不重置 - log_info "默认不重置机器码,将仅修改js文件" - - # 确保配置文件目录存在 - if [ -f "$STORAGE_FILE" ]; then - log_info "发现已有配置文件: $STORAGE_FILE" - - # 备份现有配置(以防万一) - backup_config - else - log_warn "未找到配置文件,这是正常的,脚本将跳过ID修改" - fi - - echo - log_info "配置处理完成" -} - -# 清理 Cursor 之前的修改 -clean_cursor_app() { - log_info "尝试清理 Cursor 之前的修改..." - - # 如果存在备份,直接恢复备份 - local latest_backup="" - - # 查找最新的备份 - latest_backup=$(find /tmp -name "Cursor.app.backup_*" -type d -print 2>/dev/null | sort -r | head -1) - - if [ -n "$latest_backup" ] && [ -d "$latest_backup" ]; then - log_info "找到现有备份: $latest_backup" - log_info "正在恢复原始版本..." - - # 停止 Cursor 进程 - check_and_kill_cursor - - # 恢复备份 - sudo rm -rf "$CURSOR_APP_PATH" - sudo cp -R "$latest_backup" "$CURSOR_APP_PATH" - sudo chown -R "$CURRENT_USER:staff" "$CURSOR_APP_PATH" - sudo chmod -R 755 "$CURSOR_APP_PATH" - - log_info "已恢复原始版本" - return 0 - else - log_warn "未找到现有备份,尝试重新安装 Cursor..." - echo "您可以从 https://cursor.sh 下载并重新安装 Cursor" - echo "或者继续执行此脚本,将尝试修复现有安装" - - # 可以在这里添加重新下载和安装的逻辑 - return 1 - fi -} - -# 修改 Cursor 主程序文件(安全模式) -modify_cursor_app_files() { - log_info "正在安全修改 Cursor 主程序文件..." - log_info "详细日志将记录到: $LOG_FILE" - - # 先清理之前的修改 - clean_cursor_app - - # 验证应用是否存在 - if [ ! -d "$CURSOR_APP_PATH" ]; then - log_error "未找到 Cursor.app,请确认安装路径: $CURSOR_APP_PATH" - return 1 - fi - - # 定义目标文件 - 将extensionHostProcess.js放在最前面优先处理 - local target_files=( - "${CURSOR_APP_PATH}/Contents/Resources/app/out/vs/workbench/api/node/extensionHostProcess.js" - "${CURSOR_APP_PATH}/Contents/Resources/app/out/main.js" - "${CURSOR_APP_PATH}/Contents/Resources/app/out/vs/code/node/cliProcessMain.js" - ) - - # 检查文件是否存在并且是否已修改 - local need_modification=false - local missing_files=false - - log_debug "检查目标文件..." - for file in "${target_files[@]}"; do - if [ ! -f "$file" ]; then - log_warn "文件不存在: ${file/$CURSOR_APP_PATH\//}" - echo "[FILE_CHECK] 文件不存在: $file" >> "$LOG_FILE" - missing_files=true - continue - fi - - echo "[FILE_CHECK] 文件存在: $file ($(wc -c < "$file") 字节)" >> "$LOG_FILE" - - if ! grep -q "return crypto.randomUUID()" "$file" 2>/dev/null; then - log_info "文件需要修改: ${file/$CURSOR_APP_PATH\//}" - grep -n "IOPlatformUUID" "$file" | head -3 >> "$LOG_FILE" || echo "[FILE_CHECK] 未找到 IOPlatformUUID" >> "$LOG_FILE" - need_modification=true - break - else - log_info "文件已修改: ${file/$CURSOR_APP_PATH\//}" - fi - done - - # 如果所有文件都已修改或不存在,则退出 - if [ "$missing_files" = true ]; then - log_error "部分目标文件不存在,请确认 Cursor 安装是否完整" - return 1 - fi - - if [ "$need_modification" = false ]; then - log_info "所有目标文件已经被修改过,无需重复操作" - return 0 - fi - - # 创建临时工作目录 - local timestamp=$(date +%Y%m%d_%H%M%S) - local temp_dir="/tmp/cursor_reset_${timestamp}" - local temp_app="${temp_dir}/Cursor.app" - local backup_app="/tmp/Cursor.app.backup_${timestamp}" - - log_debug "创建临时目录: $temp_dir" - echo "[TEMP_DIR] 创建临时目录: $temp_dir" >> "$LOG_FILE" - - # 清理可能存在的旧临时目录 - if [ -d "$temp_dir" ]; then - log_info "清理已存在的临时目录..." - rm -rf "$temp_dir" - fi - - # 创建新的临时目录 - mkdir -p "$temp_dir" || { - log_error "无法创建临时目录: $temp_dir" - echo "[ERROR] 无法创建临时目录: $temp_dir" >> "$LOG_FILE" - return 1 - } - - # 备份原应用 - log_info "备份原应用..." - echo "[BACKUP] 开始备份: $CURSOR_APP_PATH -> $backup_app" >> "$LOG_FILE" - - cp -R "$CURSOR_APP_PATH" "$backup_app" || { - log_error "无法创建应用备份" - echo "[ERROR] 备份失败: $CURSOR_APP_PATH -> $backup_app" >> "$LOG_FILE" - rm -rf "$temp_dir" - return 1 - } - - echo "[BACKUP] 备份完成" >> "$LOG_FILE" - - # 复制应用到临时目录 - log_info "创建临时工作副本..." - echo "[COPY] 开始复制: $CURSOR_APP_PATH -> $temp_dir" >> "$LOG_FILE" - - cp -R "$CURSOR_APP_PATH" "$temp_dir" || { - log_error "无法复制应用到临时目录" - echo "[ERROR] 复制失败: $CURSOR_APP_PATH -> $temp_dir" >> "$LOG_FILE" - rm -rf "$temp_dir" "$backup_app" - return 1 - } - - echo "[COPY] 复制完成" >> "$LOG_FILE" - - # 确保临时目录的权限正确 - chown -R "$CURRENT_USER:staff" "$temp_dir" - chmod -R 755 "$temp_dir" - - # 移除签名(增强兼容性) - log_info "移除应用签名..." - echo "[CODESIGN] 移除签名: $temp_app" >> "$LOG_FILE" - - codesign --remove-signature "$temp_app" 2>> "$LOG_FILE" || { - log_warn "移除应用签名失败" - echo "[WARN] 移除签名失败: $temp_app" >> "$LOG_FILE" - } - - # 移除所有相关组件的签名 - local components=( - "$temp_app/Contents/Frameworks/Cursor Helper.app" - "$temp_app/Contents/Frameworks/Cursor Helper (GPU).app" - "$temp_app/Contents/Frameworks/Cursor Helper (Plugin).app" - "$temp_app/Contents/Frameworks/Cursor Helper (Renderer).app" - ) - - for component in "${components[@]}"; do - if [ -e "$component" ]; then - log_info "正在移除签名: $component" - codesign --remove-signature "$component" || { - log_warn "移除组件签名失败: $component" - } - fi - done - - # 修改目标文件 - 优先处理js文件 - local modified_count=0 - local files=( - "${temp_app}/Contents/Resources/app/out/vs/workbench/api/node/extensionHostProcess.js" - "${temp_app}/Contents/Resources/app/out/main.js" - "${temp_app}/Contents/Resources/app/out/vs/code/node/cliProcessMain.js" - ) - - for file in "${files[@]}"; do - if [ ! -f "$file" ]; then - log_warn "文件不存在: ${file/$temp_dir\//}" - continue - fi - - log_debug "处理文件: ${file/$temp_dir\//}" - echo "[PROCESS] 开始处理文件: $file" >> "$LOG_FILE" - echo "[PROCESS] 文件大小: $(wc -c < "$file") 字节" >> "$LOG_FILE" - - # 输出文件部分内容到日志 - echo "[FILE_CONTENT] 文件头部 100 行:" >> "$LOG_FILE" - head -100 "$file" 2>/dev/null | grep -v "^$" | head -50 >> "$LOG_FILE" - echo "[FILE_CONTENT] ..." >> "$LOG_FILE" - - # 创建文件备份 - cp "$file" "${file}.bak" || { - log_error "无法创建文件备份: ${file/$temp_dir\//}" - echo "[ERROR] 无法创建文件备份: $file" >> "$LOG_FILE" - continue - } - - # 使用 sed 替换而不是字符串操作 - if [[ "$file" == *"extensionHostProcess.js"* ]]; then - log_debug "处理 extensionHostProcess.js 文件..." - echo "[PROCESS_DETAIL] 开始处理 extensionHostProcess.js 文件" >> "$LOG_FILE" - - # 检查是否包含目标代码 - if grep -q 'i.header.set("x-cursor-checksum' "$file"; then - log_debug "找到 x-cursor-checksum 设置代码" - echo "[FOUND] 找到 x-cursor-checksum 设置代码" >> "$LOG_FILE" - - # 记录匹配的行到日志 - grep -n 'i.header.set("x-cursor-checksum' "$file" >> "$LOG_FILE" - - # 执行特定的替换 - if sed -i.tmp 's/i\.header\.set("x-cursor-checksum",e===void 0?`${p}${t}`:`${p}${t}\/${e}`)/i.header.set("x-cursor-checksum",e===void 0?`${p}${t}`:`${p}${t}\/${p}`)/' "$file"; then - log_info "成功修改 x-cursor-checksum 设置代码" - echo "[SUCCESS] 成功完成 x-cursor-checksum 设置代码替换" >> "$LOG_FILE" - # 记录修改后的行 - grep -n 'i.header.set("x-cursor-checksum' "$file" >> "$LOG_FILE" - ((modified_count++)) - log_info "成功修改文件: ${file/$temp_dir\//}" - else - log_error "修改 x-cursor-checksum 设置代码失败" - echo "[ERROR] 替换 x-cursor-checksum 设置代码失败" >> "$LOG_FILE" - cp "${file}.bak" "$file" - fi - else - log_warn "未找到 x-cursor-checksum 设置代码" - echo "[FILE_CHECK] 未找到 x-cursor-checksum 设置代码" >> "$LOG_FILE" - - # 记录文件部分内容到日志以便排查 - echo "[FILE_CONTENT] 文件中包含 'header.set' 的行:" >> "$LOG_FILE" - grep -n "header.set" "$file" | head -20 >> "$LOG_FILE" - - echo "[FILE_CONTENT] 文件中包含 'checksum' 的行:" >> "$LOG_FILE" - grep -n "checksum" "$file" | head -20 >> "$LOG_FILE" - fi - - echo "[PROCESS_DETAIL] 完成处理 extensionHostProcess.js 文件" >> "$LOG_FILE" - elif grep -q "IOPlatformUUID" "$file"; then - log_debug "找到 IOPlatformUUID 关键字" - echo "[FOUND] 找到 IOPlatformUUID 关键字" >> "$LOG_FILE" - grep -n "IOPlatformUUID" "$file" | head -5 >> "$LOG_FILE" - - # 定位 IOPlatformUUID 相关函数 - if grep -q "function a\$" "$file"; then - # 检查是否已经修改过 - if grep -q "return crypto.randomUUID()" "$file"; then - log_info "文件已经包含 randomUUID 调用,跳过修改" - ((modified_count++)) - continue - fi - - # 针对 main.js 中发现的代码结构进行修改 - if sed -i.tmp 's/function a\$(t){switch/function a\$(t){return crypto.randomUUID(); switch/' "$file"; then - log_debug "成功注入 randomUUID 调用到 a\$ 函数" - ((modified_count++)) - log_info "成功修改文件: ${file/$temp_dir\//}" - else - log_error "修改 a\$ 函数失败" - cp "${file}.bak" "$file" - fi - elif grep -q "async function v5" "$file"; then - # 检查是否已经修改过 - if grep -q "return crypto.randomUUID()" "$file"; then - log_info "文件已经包含 randomUUID 调用,跳过修改" - ((modified_count++)) - continue - fi - - # 替代方法 - 修改 v5 函数 - if sed -i.tmp 's/async function v5(t){let e=/async function v5(t){return crypto.randomUUID(); let e=/' "$file"; then - log_debug "成功注入 randomUUID 调用到 v5 函数" - ((modified_count++)) - log_info "成功修改文件: ${file/$temp_dir\//}" - else - log_error "修改 v5 函数失败" - cp "${file}.bak" "$file" - fi - else - # 检查是否已经注入了自定义代码 - if grep -q "// Cursor ID 修改工具注入" "$file"; then - log_info "文件已经包含自定义注入代码,跳过修改" - ((modified_count++)) - continue - fi - - # 使用更通用的注入方法 - log_warn "未找到具体函数,尝试使用通用修改方法" - inject_code=" -// Cursor ID 修改工具注入 - $(date +%Y%m%d%H%M%S) -// 随机设备ID生成器注入 - $(date +%s) -const randomDeviceId_$(date +%s) = () => { - try { - return require('crypto').randomUUID(); - } catch (e) { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { - const r = Math.random() * 16 | 0; - return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); - }); - } -}; -" - # 将代码注入到文件开头 - echo "$inject_code" > "${file}.new" - cat "$file" >> "${file}.new" - mv "${file}.new" "$file" - - # 替换调用点 - sed -i.tmp 's/await v5(!1)/randomDeviceId_'"$(date +%s)"'()/g' "$file" - sed -i.tmp 's/a\$(t)/randomDeviceId_'"$(date +%s)"'()/g' "$file" - - log_debug "完成通用修改" - ((modified_count++)) - log_info "使用通用方法成功修改文件: ${file/$temp_dir\//}" - fi - else - # 未找到 IOPlatformUUID,可能是文件结构变化 - log_warn "未找到 IOPlatformUUID,尝试替代方法" - - # 检查是否已经注入或修改过 - if grep -q "return crypto.randomUUID()" "$file" || grep -q "// Cursor ID 修改工具注入" "$file"; then - log_info "文件已经被修改过,跳过修改" - ((modified_count++)) - continue - fi - - # 尝试找其他关键函数如 getMachineId 或 getDeviceId - if grep -q "function t\$()" "$file" || grep -q "async function y5" "$file"; then - log_debug "找到设备ID相关函数" - - # 修改 MAC 地址获取函数 - if grep -q "function t\$()" "$file"; then - sed -i.tmp 's/function t\$(){/function t\$(){return "00:00:00:00:00:00";/' "$file" - log_debug "修改 MAC 地址获取函数成功" - fi - - # 修改设备ID获取函数 - if grep -q "async function y5" "$file"; then - sed -i.tmp 's/async function y5(t){/async function y5(t){return crypto.randomUUID();/' "$file" - log_debug "修改设备ID获取函数成功" - fi - - ((modified_count++)) - log_info "使用替代方法成功修改文件: ${file/$temp_dir\//}" - else - # 最后尝试的通用方法 - 在文件顶部插入重写函数定义 - log_warn "未找到任何已知函数,使用最通用的方法" - - inject_universal_code=" -// Cursor ID 修改工具注入 - $(date +%Y%m%d%H%M%S) -// 全局拦截设备标识符 - $(date +%s) -const originalRequire_$(date +%s) = require; -require = function(module) { - const result = originalRequire_$(date +%s)(module); - if (module === 'crypto' && result.randomUUID) { - const originalRandomUUID_$(date +%s) = result.randomUUID; - result.randomUUID = function() { - return '${new_uuid}'; - }; - } - return result; -}; - -// 覆盖所有可能的系统ID获取函数 -global.getMachineId = function() { return '${machine_id}'; }; -global.getDeviceId = function() { return '${device_id}'; }; -global.macMachineId = '${mac_machine_id}'; -" - # 将代码注入到文件开头 - local new_uuid=$(uuidgen | tr '[:upper:]' '[:lower:]') - local machine_id="auth0|user_$(openssl rand -hex 16)" - local device_id=$(uuidgen | tr '[:upper:]' '[:lower:]') - local mac_machine_id=$(openssl rand -hex 32) - - inject_universal_code=${inject_universal_code//\$\{new_uuid\}/$new_uuid} - inject_universal_code=${inject_universal_code//\$\{machine_id\}/$machine_id} - inject_universal_code=${inject_universal_code//\$\{device_id\}/$device_id} - inject_universal_code=${inject_universal_code//\$\{mac_machine_id\}/$mac_machine_id} - - echo "$inject_universal_code" > "${file}.new" - cat "$file" >> "${file}.new" - mv "${file}.new" "$file" - - log_debug "完成通用覆盖" - ((modified_count++)) - log_info "使用最通用方法成功修改文件: ${file/$temp_dir\//}" - fi - fi - - # 添加在关键操作后记录日志 - echo "[MODIFIED] 文件修改后内容:" >> "$LOG_FILE" - grep -n "return crypto.randomUUID()" "$file" | head -3 >> "$LOG_FILE" - - # 清理临时文件 - rm -f "${file}.tmp" "${file}.bak" - echo "[PROCESS] 文件处理完成: $file" >> "$LOG_FILE" - done - - if [ "$modified_count" -eq 0 ]; then - log_error "未能成功修改任何文件" - rm -rf "$temp_dir" - return 1 - fi - - # 重新签名应用(增加重试机制) - local max_retry=3 - local retry_count=0 - local sign_success=false - - while [ $retry_count -lt $max_retry ]; do - ((retry_count++)) - log_info "尝试签名 (第 $retry_count 次)..." - - # 使用更详细的签名参数 - if codesign --sign - --force --deep --preserve-metadata=entitlements,identifier,flags "$temp_app" 2>&1 | tee /tmp/codesign.log; then - # 验证签名 - if codesign --verify -vvvv "$temp_app" 2>/dev/null; then - sign_success=true - log_info "应用签名验证通过" - break - else - log_warn "签名验证失败,错误日志:" - cat /tmp/codesign.log - fi - else - log_warn "签名失败,错误日志:" - cat /tmp/codesign.log - fi - - sleep 1 - done - - if ! $sign_success; then - log_error "经过 $max_retry 次尝试仍无法完成签名" - log_error "请手动执行以下命令完成签名:" - echo -e "${BLUE}sudo codesign --sign - --force --deep '${temp_app}'${NC}" - echo -e "${YELLOW}操作完成后,请手动将应用复制到原路径:${NC}" - echo -e "${BLUE}sudo cp -R '${temp_app}' '/Applications/'${NC}" - log_info "临时文件保留在:${temp_dir}" - return 1 - fi - - # 替换原应用 - log_info "安装修改版应用..." - if ! sudo rm -rf "$CURSOR_APP_PATH" || ! sudo cp -R "$temp_app" "/Applications/"; then - log_error "应用替换失败,正在恢复..." - sudo rm -rf "$CURSOR_APP_PATH" - sudo cp -R "$backup_app" "$CURSOR_APP_PATH" - rm -rf "$temp_dir" "$backup_app" - return 1 - fi - - # 清理临时文件 - rm -rf "$temp_dir" "$backup_app" - - # 设置权限 - sudo chown -R "$CURRENT_USER:staff" "$CURSOR_APP_PATH" - sudo chmod -R 755 "$CURSOR_APP_PATH" - - log_info "Cursor 主程序文件修改完成!原版备份在: ${backup_app/$HOME/\~}" - return 0 -} - -# 显示文件树结构 -show_file_tree() { - local base_dir=$(dirname "$STORAGE_FILE") - echo - log_info "文件结构:" - echo -e "${BLUE}$base_dir${NC}" - echo "├── globalStorage" - echo "│ ├── storage.json (已修改)" - echo "│ └── backups" - - # 列出备份文件 - if [ -d "$BACKUP_DIR" ]; then - local backup_files=("$BACKUP_DIR"/*) - if [ ${#backup_files[@]} -gt 0 ]; then - for file in "${backup_files[@]}"; do - if [ -f "$file" ]; then - echo "│ └── $(basename "$file")" - fi - done - else - echo "│ └── (空)" - fi - fi - echo -} - -# 显示公众号信息 -show_follow_info() { - echo - echo -e "${GREEN}================================${NC}" - echo -e "${YELLOW} 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) ${NC}" - echo -e "${GREEN}================================${NC}" - echo -} - -# 禁用自动更新 -disable_auto_update() { - local updater_path="$HOME/Library/Application Support/Caches/cursor-updater" - local app_update_yml="/Applications/Cursor.app/Contents/Resources/app-update.yml" - - echo - log_info "正在禁用 Cursor 自动更新..." - - # 备份并清空 app-update.yml - if [ -f "$app_update_yml" ]; then - log_info "备份并修改 app-update.yml..." - if ! sudo cp "$app_update_yml" "${app_update_yml}.bak" 2>/dev/null; then - log_warn "备份 app-update.yml 失败,继续执行..." - fi - - if sudo bash -c "echo '' > \"$app_update_yml\"" && \ - sudo chmod 444 "$app_update_yml"; then - log_info "成功禁用 app-update.yml" - else - log_error "修改 app-update.yml 失败,请手动执行以下命令:" - echo -e "${BLUE}sudo cp \"$app_update_yml\" \"${app_update_yml}.bak\"${NC}" - echo -e "${BLUE}sudo bash -c 'echo \"\" > \"$app_update_yml\"'${NC}" - echo -e "${BLUE}sudo chmod 444 \"$app_update_yml\"${NC}" - fi - else - log_warn "未找到 app-update.yml 文件" - fi - - # 同时也处理 cursor-updater - log_info "处理 cursor-updater..." - if sudo rm -rf "$updater_path" && \ - sudo touch "$updater_path" && \ - sudo chmod 444 "$updater_path"; then - log_info "成功禁用 cursor-updater" - else - log_error "禁用 cursor-updater 失败,请手动执行以下命令:" - echo -e "${BLUE}sudo rm -rf \"$updater_path\" && sudo touch \"$updater_path\" && sudo chmod 444 \"$updater_path\"${NC}" - fi - - echo - log_info "验证方法:" - echo "1. 运行命令:ls -l \"$updater_path\"" - echo " 确认文件权限显示为:r--r--r--" - echo "2. 运行命令:ls -l \"$app_update_yml\"" - echo " 确认文件权限显示为:r--r--r--" - echo - log_info "完成后请重启 Cursor" -} - -# 新增恢复功能选项 -restore_feature() { - # 检查备份目录是否存在 - if [ ! -d "$BACKUP_DIR" ]; then - log_warn "备份目录不存在" - return 1 - fi - - # 使用 find 命令获取备份文件列表并存储到数组 - backup_files=() - while IFS= read -r file; do - [ -f "$file" ] && backup_files+=("$file") - done < <(find "$BACKUP_DIR" -name "*.backup_*" -type f 2>/dev/null | sort) - - # 检查是否找到备份文件 - if [ ${#backup_files[@]} -eq 0 ]; then - log_warn "未找到任何备份文件" - return 1 - fi - - echo - log_info "可用的备份文件:" - - # 构建菜单选项字符串 - menu_options="退出 - 不恢复任何文件" - for i in "${!backup_files[@]}"; do - menu_options="$menu_options|$(basename "${backup_files[$i]}")" - done - - # 使用菜单选择函数 - select_menu_option "请使用上下箭头选择要恢复的备份文件,按Enter确认:" "$menu_options" 0 - choice=$? - - # 处理用户输入 - if [ "$choice" = "0" ]; then - log_info "跳过恢复操作" - return 0 - fi - - # 获取选择的备份文件 (减1是因为第一个选项是"退出") - local selected_backup="${backup_files[$((choice-1))]}" - - # 验证文件存在性和可读性 - if [ ! -f "$selected_backup" ] || [ ! -r "$selected_backup" ]; then - log_error "无法访问选择的备份文件" - return 1 - fi - - # 尝试恢复配置 - if cp "$selected_backup" "$STORAGE_FILE"; then - chmod 644 "$STORAGE_FILE" - chown "$CURRENT_USER" "$STORAGE_FILE" - log_info "已从备份文件恢复配置: $(basename "$selected_backup")" - return 0 - else - log_error "恢复配置失败" - return 1 - fi -} - -# 解决"应用已损坏,无法打开"问题 -fix_damaged_app() { - log_info "正在修复"应用已损坏"问题..." - - # 检查Cursor应用是否存在 - if [ ! -d "$CURSOR_APP_PATH" ]; then - log_error "未找到Cursor应用: $CURSOR_APP_PATH" - return 1 - fi - - log_info "尝试移除隔离属性..." - if sudo find "$CURSOR_APP_PATH" -print0 \ - | xargs -0 sudo xattr -d com.apple.quarantine 2>/dev/null - log_info "成功移除隔离属性" - else - log_warn "移除隔离属性失败,尝试其他方法..." - fi - - log_info "尝试重新签名应用..." - if sudo codesign --force --deep --sign - "$CURSOR_APP_PATH" 2>/dev/null; then - log_info "应用重新签名成功" - else - log_warn "应用重新签名失败" - fi - - echo - log_info "修复完成!请尝试重新打开Cursor应用" - echo - echo -e "${YELLOW}如果仍然无法打开,您可以尝试以下方法:${NC}" - echo "1. 在系统偏好设置->安全性与隐私中,点击"仍要打开"按钮" - echo "2. 暂时关闭Gatekeeper(不建议): sudo spctl --master-disable" - echo "3. 重新下载安装Cursor应用" - echo - echo -e "${BLUE}参考链接: https://sysin.org/blog/macos-if-crashes-when-opening/${NC}" - - return 0 -} - -# 新增:通用菜单选择函数 -# 参数: -# $1 - 提示信息 -# $2 - 选项数组,格式为 "选项1|选项2|选项3" -# $3 - 默认选项索引 (从0开始) -# 返回: 选中的选项索引 (从0开始) -select_menu_option() { - local prompt="$1" - IFS='|' read -ra options <<< "$2" - local default_index=${3:-0} - local selected_index=$default_index - local key_input - local cursor_up='\033[A' - local cursor_down='\033[B' - local enter_key=$'\n' - - # 保存光标位置 - tput sc - - # 显示提示信息 - echo -e "$prompt" - - # 第一次显示菜单 - for i in "${!options[@]}"; do - if [ $i -eq $selected_index ]; then - echo -e " ${GREEN}►${NC} ${options[$i]}" - else - echo -e " ${options[$i]}" - fi - done - - # 循环处理键盘输入 - while true; do - # 读取单个按键 - read -rsn3 key_input - - # 检测按键 - case "$key_input" in - # 上箭头键 - $'\033[A') - if [ $selected_index -gt 0 ]; then - ((selected_index--)) - fi - ;; - # 下箭头键 - $'\033[B') - if [ $selected_index -lt $((${#options[@]}-1)) ]; then - ((selected_index++)) - fi - ;; - # Enter键 - "") - echo # 换行 - log_info "您选择了: ${options[$selected_index]}" - return $selected_index - ;; - esac - - # 恢复光标位置 - tput rc - - # 重新显示菜单 - for i in "${!options[@]}"; do - if [ $i -eq $selected_index ]; then - echo -e " ${GREEN}►${NC} ${options[$i]}" - else - echo -e " ${options[$i]}" - fi - done - done -} - -# 主函数 -main() { - - # 初始化日志文件 - initialize_log - log_info "脚本启动..." - - # 记录系统信息 - log_info "系统信息: $(uname -a)" - log_info "当前用户: $CURRENT_USER" - log_cmd_output "sw_vers" "macOS 版本信息" - log_cmd_output "which codesign" "codesign 路径" - log_cmd_output "ls -la \"$CURSOR_APP_PATH\"" "Cursor 应用信息" - - # 新增环境检查 - if [[ $(uname) != "Darwin" ]]; then - log_error "本脚本仅支持 macOS 系统" - exit 1 - fi - - clear - # 显示 Logo - echo -e " - ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ - ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ - ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ - ██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ - ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ - ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ - " - echo -e "${BLUE}================================${NC}" - echo -e "${GREEN}🚀 Cursor 防掉试用Pro删除工具 ${NC}" - echo -e "${YELLOW}📱 关注公众号【煎饼果子卷AI】 ${NC}" - echo -e "${YELLOW}🤝 一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) ${NC}" - echo -e "${BLUE}================================${NC}" - echo - echo -e "${YELLOW}💡 [重要提示]${NC} 本工具采用分阶段执行策略,既能彻底清理又能修改机器码" - echo -e "${YELLOW}💡 [重要提示]${NC} 本工具免费,如果对您有帮助,请关注公众号【煎饼果子卷AI】" - echo - - # 📋 执行流程说明 - echo - echo -e "${GREEN}📋 [执行流程]${NC} 本脚本将按以下步骤执行:" - echo -e "${BLUE} 1️⃣ 检测并关闭Cursor进程${NC}" - echo -e "${BLUE} 2️⃣ 保存Cursor程序路径信息${NC}" - echo -e "${BLUE} 3️⃣ 删除指定的Cursor试用相关文件夹${NC}" - echo -e "${BLUE} 📁 ~/Library/Application Support/Cursor${NC}" - echo -e "${BLUE} 📁 ~/.cursor${NC}" - echo -e "${BLUE} 3.5️⃣ 预创建必要目录结构,避免权限问题${NC}" - echo -e "${BLUE} 4️⃣ 重新启动Cursor让其生成新的配置文件${NC}" - echo -e "${BLUE} 5️⃣ 等待配置文件生成完成(最多45秒)${NC}" - echo -e "${BLUE} 6️⃣ 关闭Cursor进程${NC}" - echo -e "${BLUE} 7️⃣ 修改新生成的机器码配置文件${NC}" - echo -e "${BLUE} 8️⃣ 显示操作完成统计信息${NC}" - echo - echo -e "${YELLOW}⚠️ [注意事项]${NC}" - echo -e "${YELLOW} • 脚本执行过程中请勿手动操作Cursor${NC}" - echo -e "${YELLOW} • 建议在执行前关闭所有Cursor窗口${NC}" - echo -e "${YELLOW} • 执行完成后需要重新启动Cursor${NC}" - echo -e "${YELLOW} • 原配置文件会自动备份到backups文件夹${NC}" - echo -e "${YELLOW} • 需要Python3环境来处理JSON配置文件${NC}" - echo - - # 🤔 用户确认 - echo -e "${GREEN}🤔 [确认]${NC} 请确认您已了解上述执行流程" - read -p "是否继续执行?(输入 y 或 yes 继续,其他任意键退出): " confirmation - if [[ ! "$confirmation" =~ ^(y|yes)$ ]]; then - echo -e "${YELLOW}👋 [退出]${NC} 用户取消执行,脚本退出" - exit 0 - fi - echo -e "${GREEN}✅ [确认]${NC} 用户确认继续执行" - echo - - # 🚀 执行主要功能 - check_permissions - check_and_kill_cursor - - # 🚨 重要警告提示 - echo - echo -e "${RED}🚨 [重要警告]${NC} ============================================" - log_warn "⚠️ [风控提醒] Cursor 风控机制非常严格!" - log_warn "⚠️ [必须删除] 必须完全删除指定文件夹,不能有任何残留设置" - log_warn "⚠️ [防掉试用] 只有彻底清理才能有效防止掉试用Pro状态" - echo -e "${RED}🚨 [重要警告]${NC} ============================================" - echo - - # 🎯 执行 Cursor 防掉试用Pro删除文件夹功能 - log_info "🚀 [开始] 开始执行核心功能..." - remove_cursor_trial_folders - - # 🔄 重启Cursor让其重新生成配置文件 - restart_cursor_and_wait - - # 🛠️ 修改机器码配置 - modify_machine_code_config - - # 🎉 显示操作完成信息 - echo - log_info "🎉 [完成] Cursor 防掉试用Pro删除操作已完成!" - echo - - # 📱 显示公众号信息 - echo -e "${GREEN}================================${NC}" - echo -e "${YELLOW}📱 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) ${NC}" - echo -e "${GREEN}================================${NC}" - echo - log_info "🚀 [提示] 现在可以重新启动 Cursor 尝试使用了!" - echo - - # 🚫 以下功能已暂时屏蔽 - log_warn "⚠️ [提示] 以下功能已暂时屏蔽:" - log_info "📋 [说明] - 自动更新禁用功能" - log_info "📋 [说明] - 应用修复功能" - log_info "📋 [说明] 如需恢复这些功能,请联系开发者" - echo - - # 🎉 脚本执行完成 - log_info "🎉 [完成] 所有操作已完成!" - echo - log_info "💡 [提示] 如果需要恢复机器码修改功能,请联系开发者" - log_warn "⚠️ [注意] 重启 Cursor 后生效" - echo - log_info "🚀 [下一步] 现在可以启动 Cursor 尝试使用了!" - echo - - # 记录脚本完成信息 - log_info "📝 [日志] 脚本执行完成" - echo "========== Cursor 防掉试用Pro删除工具日志结束 $(date) ==========" >> "$LOG_FILE" - - # 显示日志文件位置 - echo - log_info "📄 [日志] 详细日志已保存到: $LOG_FILE" - echo "如遇问题请将此日志文件提供给开发者以协助排查" - echo -} - -# 执行主函数 -main - diff --git a/scripts/run/cursor_mac_id_modifier_new.sh b/scripts/run/cursor_mac_id_modifier_new.sh deleted file mode 100644 index 6eaff20..0000000 --- a/scripts/run/cursor_mac_id_modifier_new.sh +++ /dev/null @@ -1,688 +0,0 @@ -#!/bin/bash - -# ======================================== -# Cursor macOS 机器码修改脚本 (重构精简版) -# ======================================== -# -# 🎯 重构目标: -# - 简化脚本复杂度,从3158行压缩到约900行 -# - 自动化权限修复,解决EACCES权限错误 -# - 减少用户交互步骤,提升执行效率 -# - 保持所有原有功能完整性 -# -# 🚀 执行流程说明: -# 1. 环境检测和权限预修复 -# 2. 用户选择执行模式(仅修改 vs 完整重置) -# 3. 自动执行所有必要步骤 -# 4. 智能设备识别绕过(MAC地址或JS内核修改) -# 5. 自动权限修复和验证 -# -# ======================================== - -set -e - -# ==================== 核心配置 ==================== -LOG_FILE="/tmp/cursor_reset_$(date +%Y%m%d_%H%M%S).log" -CURSOR_APP_PATH="/Applications/Cursor.app" -STORAGE_FILE="$HOME/Library/Application Support/Cursor/User/globalStorage/storage.json" -BACKUP_DIR="$HOME/Library/Application Support/Cursor/User/globalStorage/backups" - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -# ==================== 统一工具函数 ==================== - -# 初始化日志 -init_log() { - echo "========== Cursor重构脚本执行日志 $(date) ==========" > "$LOG_FILE" - chmod 644 "$LOG_FILE" -} - -# 精简日志函数 -log() { - local level="$1" - local msg="$2" - local color="" - - case "$level" in - "INFO") color="$GREEN" ;; - "WARN") color="$YELLOW" ;; - "ERROR") color="$RED" ;; - *) color="$BLUE" ;; - esac - - echo -e "${color}[$level]${NC} $msg" - echo "[$level] $(date '+%H:%M:%S') $msg" >> "$LOG_FILE" -} - -# 统一权限管理器 - 解决所有权限问题 -fix_permissions() { - log "INFO" "🔧 执行统一权限修复..." - - local cursor_support="$HOME/Library/Application Support/Cursor" - local cursor_home="$HOME/.cursor" - - # 创建必要目录结构 - local dirs=( - "$cursor_support" - "$cursor_support/User" - "$cursor_support/User/globalStorage" - "$cursor_support/logs" - "$cursor_support/CachedData" - "$cursor_home" - "$cursor_home/extensions" - ) - - for dir in "${dirs[@]}"; do - mkdir -p "$dir" 2>/dev/null || true - done - - # 执行核心权限修复命令 - if sudo chown -R "$(whoami)" "$cursor_support" 2>/dev/null && \ - sudo chown -R "$(whoami)" "$cursor_home" 2>/dev/null && \ - chmod -R u+w "$cursor_support" 2>/dev/null && \ - chmod -R u+w "$cursor_home/extensions" 2>/dev/null; then - log "INFO" "✅ 权限修复成功" - return 0 - else - log "ERROR" "❌ 权限修复失败" - return 1 - fi -} - -# 环境检测器 -detect_environment() { - log "INFO" "🔍 检测系统环境..." - - # 检测macOS版本和硬件 - MACOS_VERSION=$(sw_vers -productVersion) - HARDWARE_TYPE=$(uname -m) - - if [[ "$HARDWARE_TYPE" == "arm64" ]]; then - HARDWARE_TYPE="Apple Silicon" - else - HARDWARE_TYPE="Intel" - fi - - # 检测兼容性 - local macos_major=$(echo "$MACOS_VERSION" | cut -d. -f1) - if [[ $macos_major -ge 14 ]] || [[ "$HARDWARE_TYPE" == "Apple Silicon" ]]; then - MAC_COMPATIBLE=false - log "WARN" "⚠️ 检测到MAC地址修改受限环境: macOS $MACOS_VERSION ($HARDWARE_TYPE)" - else - MAC_COMPATIBLE=true - log "INFO" "✅ 环境兼容性检查通过" - fi - - # 检查Python3 - if ! command -v python3 >/dev/null 2>&1; then - log "ERROR" "❌ 未找到Python3,请安装: brew install python3" - return 1 - fi - - # 检查Cursor应用 - if [ ! -d "$CURSOR_APP_PATH" ]; then - log "ERROR" "❌ 未找到Cursor应用: $CURSOR_APP_PATH" - return 1 - fi - - log "INFO" "✅ 环境检测完成: macOS $MACOS_VERSION ($HARDWARE_TYPE)" - return 0 -} - -# 进程管理器 -manage_cursor_process() { - local action="$1" # kill 或 start - - case "$action" in - "kill") - log "INFO" "🔄 关闭Cursor进程..." - pkill -f "Cursor" 2>/dev/null || true - sleep 2 - - # 验证是否关闭 - if pgrep -f "Cursor" >/dev/null; then - pkill -9 -f "Cursor" 2>/dev/null || true - sleep 2 - fi - log "INFO" "✅ Cursor进程已关闭" - ;; - "start") - log "INFO" "🚀 启动Cursor..." - "$CURSOR_APP_PATH/Contents/MacOS/Cursor" > /dev/null 2>&1 & - sleep 15 - log "INFO" "✅ Cursor已启动" - ;; - esac -} - -# 错误处理器 -handle_error() { - local error_msg="$1" - local recovery_action="$2" - - log "ERROR" "❌ 错误: $error_msg" - - if [ -n "$recovery_action" ]; then - log "INFO" "🔄 尝试恢复: $recovery_action" - eval "$recovery_action" - fi - - log "INFO" "💡 如需帮助,请查看日志: $LOG_FILE" -} - -# ==================== 功能模块 ==================== - -# 机器码修改器 -modify_machine_code() { - log "INFO" "🛠️ 开始修改机器码配置..." - - # 检查配置文件 - if [ ! -f "$STORAGE_FILE" ]; then - log "ERROR" "❌ 配置文件不存在,请先启动Cursor生成配置" - return 1 - fi - - # 创建备份 - mkdir -p "$BACKUP_DIR" - local backup_file="$BACKUP_DIR/storage.json.backup_$(date +%Y%m%d_%H%M%S)" - cp "$STORAGE_FILE" "$backup_file" || { - log "ERROR" "❌ 备份失败" - return 1 - } - - # 生成新ID - local machine_id="auth0|user_$(openssl rand -hex 16)" - local mac_machine_id=$(uuidgen | tr '[:upper:]' '[:lower:]') - local device_id=$(uuidgen | tr '[:upper:]' '[:lower:]') - local sqm_id="{$(uuidgen | tr '[:lower:]' '[:upper:]')}" - - # 修改配置文件 - local python_result=$(python3 -c " -import json -import sys - -try: - with open('$STORAGE_FILE', 'r', encoding='utf-8') as f: - config = json.load(f) - - config['telemetry.machineId'] = '$machine_id' - config['telemetry.macMachineId'] = '$mac_machine_id' - config['telemetry.devDeviceId'] = '$device_id' - config['telemetry.sqmId'] = '$sqm_id' - - with open('$STORAGE_FILE', 'w', encoding='utf-8') as f: - json.dump(config, f, indent=2, ensure_ascii=False) - - print('SUCCESS') -except Exception as e: - print(f'ERROR: {e}') - sys.exit(1) -" 2>&1) - - if echo "$python_result" | grep -q "SUCCESS"; then - # 设置只读保护 - chmod 444 "$STORAGE_FILE" 2>/dev/null || true - log "INFO" "✅ 机器码修改成功" - log "INFO" "💾 备份保存至: $(basename "$backup_file")" - return 0 - else - log "ERROR" "❌ 机器码修改失败: $python_result" - cp "$backup_file" "$STORAGE_FILE" 2>/dev/null || true - return 1 - fi -} - -# 智能设备绕过器 - 根据环境自动选择最佳方案 -bypass_device_detection() { - log "INFO" "🔧 开始智能设备识别绕过..." - - # 根据环境兼容性选择方案 - if [ "$MAC_COMPATIBLE" = false ]; then - log "INFO" "💡 检测到MAC地址修改受限,使用JS内核修改方案" - return modify_js_kernel - else - log "INFO" "💡 尝试MAC地址修改方案" - if modify_mac_address; then - return 0 - else - log "WARN" "⚠️ MAC地址修改失败,切换到JS内核修改" - return modify_js_kernel - fi - fi -} - -# MAC地址修改器(简化版) -modify_mac_address() { - log "INFO" "🌐 开始MAC地址修改..." - - # 获取活动网络接口 - local interfaces=() - while IFS= read -r line; do - if [[ $line == "Hardware Port: Wi-Fi" || $line == "Hardware Port: Ethernet" ]]; then - read -r dev_line - local device=$(echo "$dev_line" | awk '{print $2}') - if [ -n "$device" ] && ifconfig "$device" 2>/dev/null | grep -q "status: active"; then - interfaces+=("$device") - fi - fi - done < <(networksetup -listallhardwareports) - - if [ ${#interfaces[@]} -eq 0 ]; then - log "WARN" "⚠️ 未找到活动网络接口" - return 1 - fi - - local success_count=0 - for interface in "${interfaces[@]}"; do - log "INFO" "🔧 处理接口: $interface" - - # 生成新MAC地址 - local new_mac=$(printf '%02x:%02x:%02x:%02x:%02x:%02x' \ - $(( (RANDOM & 0xFC) | 0x02 )) $((RANDOM%256)) $((RANDOM%256)) \ - $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256))) - - # 尝试修改MAC地址 - if sudo ifconfig "$interface" down 2>/dev/null && \ - sleep 2 && \ - sudo ifconfig "$interface" ether "$new_mac" 2>/dev/null && \ - sudo ifconfig "$interface" up 2>/dev/null; then - log "INFO" "✅ 接口 $interface MAC地址修改成功: $new_mac" - ((success_count++)) - else - log "WARN" "⚠️ 接口 $interface MAC地址修改失败" - fi - sleep 2 - done - - if [ $success_count -gt 0 ]; then - log "INFO" "✅ MAC地址修改完成 ($success_count/${#interfaces[@]} 成功)" - return 0 - else - return 1 - fi -} - -# JS内核修改器(简化版) -modify_js_kernel() { - log "INFO" "🔧 开始JS内核修改..." - - # 关闭Cursor - manage_cursor_process "kill" - - # 目标JS文件 - local js_files=( - "$CURSOR_APP_PATH/Contents/Resources/app/out/vs/workbench/api/node/extensionHostProcess.js" - "$CURSOR_APP_PATH/Contents/Resources/app/out/main.js" - ) - - # 检查是否需要修改 - local need_modify=false - for file in "${js_files[@]}"; do - if [ -f "$file" ] && ! grep -q "return crypto.randomUUID()" "$file" 2>/dev/null; then - need_modify=true - break - fi - done - - if [ "$need_modify" = false ]; then - log "INFO" "✅ JS文件已修改,跳过" - return 0 - fi - - # 创建备份 - local backup_app="/tmp/Cursor.app.backup_$(date +%Y%m%d_%H%M%S)" - cp -R "$CURSOR_APP_PATH" "$backup_app" || { - log "ERROR" "❌ 创建备份失败" - return 1 - fi - - # 生成设备ID - local new_uuid=$(uuidgen | tr '[:upper:]' '[:lower:]') - local machine_id="auth0|user_$(openssl rand -hex 16)" - - # 修改JS文件 - local modified_count=0 - for file in "${js_files[@]}"; do - if [ ! -f "$file" ]; then - continue - fi - - log "INFO" "📝 处理文件: $(basename "$file")" - - # 创建注入代码 - local inject_code=" -// Cursor设备标识符劫持 - $(date +%Y%m%d%H%M%S) -import crypto from 'crypto'; -const originalRandomUUID = crypto.randomUUID; -crypto.randomUUID = function() { return '$new_uuid'; }; -globalThis.getMachineId = function() { return '$machine_id'; }; -console.log('Cursor设备标识符已劫持'); -" - - # 注入代码 - echo "$inject_code" > "${file}.new" - cat "$file" >> "${file}.new" - mv "${file}.new" "$file" - - ((modified_count++)) - log "INFO" "✅ 文件修改成功: $(basename "$file")" - done - - if [ $modified_count -gt 0 ]; then - # 重新签名 - if codesign --sign - --force --deep "$CURSOR_APP_PATH" 2>/dev/null; then - log "INFO" "✅ JS内核修改完成 ($modified_count 个文件)" - return 0 - else - log "WARN" "⚠️ 签名失败,但修改已完成" - return 0 - fi - else - log "ERROR" "❌ 未修改任何文件" - return 1 - fi -} - -# 环境重置器 -reset_environment() { - log "INFO" "🗑️ 开始环境重置..." - - # 关闭Cursor - manage_cursor_process "kill" - - # 删除目标文件夹 - local folders=( - "$HOME/Library/Application Support/Cursor" - "$HOME/.cursor" - ) - - local deleted_count=0 - for folder in "${folders[@]}"; do - if [ -d "$folder" ]; then - if rm -rf "$folder"; then - log "INFO" "✅ 已删除: $folder" - ((deleted_count++)) - else - log "ERROR" "❌ 删除失败: $folder" - fi - fi - done - - # 修复权限 - fix_permissions - - log "INFO" "✅ 环境重置完成 (删除 $deleted_count 个文件夹)" - return 0 -} - -# 禁用自动更新 -disable_auto_update() { - log "INFO" "🚫 禁用自动更新..." - - local app_update_yml="$CURSOR_APP_PATH/Contents/Resources/app-update.yml" - local updater_path="$HOME/Library/Application Support/Caches/cursor-updater" - - # 禁用app-update.yml - if [ -f "$app_update_yml" ]; then - sudo cp "$app_update_yml" "${app_update_yml}.bak" 2>/dev/null || true - sudo bash -c "echo '' > \"$app_update_yml\"" 2>/dev/null || true - sudo chmod 444 "$app_update_yml" 2>/dev/null || true - fi - - # 禁用cursor-updater - sudo rm -rf "$updater_path" 2>/dev/null || true - sudo touch "$updater_path" 2>/dev/null || true - sudo chmod 444 "$updater_path" 2>/dev/null || true - - log "INFO" "✅ 自动更新已禁用" -} - -# 修复应用签名问题 -fix_app_signature() { - log "INFO" "🔧 修复应用签名..." - - # 移除隔离属性 - sudo find "$CURSOR_APP_PATH" -print0 2>/dev/null | \ - xargs -0 sudo xattr -d com.apple.quarantine 2>/dev/null || true - - # 重新签名 - sudo codesign --force --deep --sign - "$CURSOR_APP_PATH" 2>/dev/null || true - - log "INFO" "✅ 应用签名修复完成" -} - -# ==================== 主执行流程 ==================== - -# 快速模式 - 仅修改机器码 -quick_mode() { - log "INFO" "🚀 执行快速模式(仅修改机器码)..." - - # 检查环境 - if ! detect_environment; then - handle_error "环境检测失败" "exit 1" - return 1 - fi - - # 预修复权限 - fix_permissions - - # 修改机器码 - if ! modify_machine_code; then - handle_error "机器码修改失败" "exit 1" - return 1 - fi - - # 设备绕过 - bypass_device_detection || log "WARN" "⚠️ 设备绕过失败,但机器码修改已完成" - - # 禁用更新 - disable_auto_update - - # 修复签名 - fix_app_signature - - # 最终权限修复 - fix_permissions - - log "INFO" "🎉 快速模式执行完成!" - return 0 -} - -# 完整模式 - 重置环境+修改机器码 -full_mode() { - log "INFO" "🚀 执行完整模式(重置环境+修改机器码)..." - - # 检查环境 - if ! detect_environment; then - handle_error "环境检测失败" "exit 1" - return 1 - fi - - # 环境重置 - if ! reset_environment; then - handle_error "环境重置失败" "exit 1" - return 1 - fi - - # 启动Cursor生成配置 - manage_cursor_process "start" - - # 等待配置文件生成 - local config_wait=0 - while [ ! -f "$STORAGE_FILE" ] && [ $config_wait -lt 30 ]; do - sleep 2 - ((config_wait += 2)) - log "INFO" "⏳ 等待配置文件生成... ($config_wait/30秒)" - done - - # 关闭Cursor - manage_cursor_process "kill" - - # 修改机器码 - if ! modify_machine_code; then - handle_error "机器码修改失败" "exit 1" - return 1 - fi - - # 设备绕过 - bypass_device_detection || log "WARN" "⚠️ 设备绕过失败,但机器码修改已完成" - - # 禁用更新 - disable_auto_update - - # 修复签名 - fix_app_signature - - # 最终权限修复 - fix_permissions - - log "INFO" "🎉 完整模式执行完成!" - return 0 -} - -# ==================== 用户界面 ==================== - -# 显示Logo和信息 -show_header() { - clear - echo -e " - ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ - ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ - ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ - ██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ - ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ - ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ - " - echo -e "${BLUE}================================${NC}" - echo -e "${GREEN}🚀 Cursor 机器码修改工具 (重构版) ${NC}" - echo -e "${YELLOW}📱 关注公众号【煎饼果子卷AI】 ${NC}" - echo -e "${BLUE}================================${NC}" - echo - echo -e "${YELLOW}💡 [免费工具]${NC} 如果对您有帮助,请关注公众号支持开发者" - echo -} - -# 用户选择菜单 -user_menu() { - echo -e "${GREEN}🎯 [选择模式]${NC} 请选择执行模式:" - echo - echo -e "${BLUE} 1️⃣ 快速模式 - 仅修改机器码${NC}" - echo -e "${YELLOW} • 保留现有配置和数据${NC}" - echo -e "${YELLOW} • 执行时间约30秒${NC}" - echo -e "${YELLOW} • 自动权限修复${NC}" - echo - echo -e "${BLUE} 2️⃣ 完整模式 - 重置环境+修改机器码${NC}" - echo -e "${RED} • 删除所有Cursor配置(请备份)${NC}" - echo -e "${YELLOW} • 执行时间约90秒${NC}" - echo -e "${YELLOW} • 彻底重置试用状态${NC}" - echo - - while true; do - read -p "请输入选择 (1 或 2): " choice - case "$choice" in - 1) - log "INFO" "✅ 用户选择:快速模式" - return 1 - ;; - 2) - echo -e "${RED}⚠️ [警告]${NC} 完整模式将删除所有Cursor配置!" - read -p "确认执行?(输入 yes 确认): " confirm - if [ "$confirm" = "yes" ]; then - log "INFO" "✅ 用户选择:完整模式" - return 2 - else - echo -e "${YELLOW}👋 [取消]${NC} 请重新选择" - continue - fi - ;; - *) - echo -e "${RED}❌ [错误]${NC} 无效选择,请输入 1 或 2" - ;; - esac - done -} - -# 显示完成信息 -show_completion() { - echo - echo -e "${GREEN}================================${NC}" - echo -e "${BLUE} 🎯 执行完成总结 ${NC}" - echo -e "${GREEN}================================${NC}" - echo -e "${GREEN}✅ 机器码配置: 已修改${NC}" - echo -e "${GREEN}✅ 设备识别绕过: 已完成${NC}" - echo -e "${GREEN}✅ 自动更新: 已禁用${NC}" - echo -e "${GREEN}✅ 权限修复: 已完成${NC}" - echo -e "${GREEN}✅ 应用签名: 已修复${NC}" - echo -e "${GREEN}================================${NC}" - echo - echo -e "${YELLOW}📱 关注公众号【煎饼果子卷AI】获取更多Cursor技巧${NC}" - echo - echo -e "${BLUE}🚀 [下一步]${NC} 现在可以启动Cursor使用了!" - echo -e "${BLUE}📄 [日志]${NC} 详细日志保存在: $LOG_FILE" - echo -} - -# ==================== 主函数 ==================== - -main() { - # 检查权限 - if [ "$EUID" -ne 0 ]; then - echo -e "${RED}❌ [错误]${NC} 请使用 sudo 运行此脚本" - echo "示例: sudo $0" - exit 1 - fi - - # 检查macOS - if [[ $(uname) != "Darwin" ]]; then - echo -e "${RED}❌ [错误]${NC} 本脚本仅支持 macOS 系统" - exit 1 - fi - - # 初始化 - init_log - log "INFO" "🚀 Cursor重构脚本启动..." - - # 预修复权限 - fix_permissions - - # 显示界面 - show_header - - # 用户选择 - user_menu - local mode=$? - - echo - log "INFO" "🚀 开始执行,请稍候..." - echo - - # 执行对应模式 - case $mode in - 1) - if quick_mode; then - show_completion - exit 0 - else - log "ERROR" "❌ 快速模式执行失败" - exit 1 - fi - ;; - 2) - if full_mode; then - show_completion - exit 0 - else - log "ERROR" "❌ 完整模式执行失败" - exit 1 - fi - ;; - esac -} - -# 执行主函数 -main "$@" diff --git a/scripts/run/cursor_win_id_modifier_old.ps1 b/scripts/run/cursor_win_id_modifier_old.ps1 deleted file mode 100644 index dde8fe1..0000000 --- a/scripts/run/cursor_win_id_modifier_old.ps1 +++ /dev/null @@ -1,607 +0,0 @@ -# 设置输出编码为 UTF-8 -$OutputEncoding = [System.Text.Encoding]::UTF8 -[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 - -# 颜色定义 -$RED = "`e[31m" -$GREEN = "`e[32m" -$YELLOW = "`e[33m" -$BLUE = "`e[34m" -$NC = "`e[0m" - -# 配置文件路径 -$STORAGE_FILE = "$env:APPDATA\Cursor\User\globalStorage\storage.json" -$BACKUP_DIR = "$env:APPDATA\Cursor\User\globalStorage\backups" - -# 新增 Cursor 初始化函数 -function Cursor-初始化 { - Write-Host "$GREEN[信息]$NC 正在执行 Cursor 初始化清理..." - $BASE_PATH = "$env:APPDATA\Cursor\User" - - $filesToDelete = @( - (Join-Path -Path $BASE_PATH -ChildPath "globalStorage\\state.vscdb"), - (Join-Path -Path $BASE_PATH -ChildPath "globalStorage\\state.vscdb.backup") - ) - - $folderToCleanContents = Join-Path -Path $BASE_PATH -ChildPath "History" - $folderToDeleteCompletely = Join-Path -Path $BASE_PATH -ChildPath "workspaceStorage" - - Write-Host "$BLUE[调试]$NC 基础路径: $BASE_PATH" - - # 删除指定文件 - foreach ($file in $filesToDelete) { - Write-Host "$BLUE[调试]$NC 检查文件: $file" - if (Test-Path $file) { - try { - Remove-Item -Path $file -Force -ErrorAction Stop - Write-Host "$GREEN[成功]$NC 已删除文件: $file" - } - catch { - Write-Host "$RED[错误]$NC 删除文件 $file 失败: $($_.Exception.Message)" - } - } else { - Write-Host "$YELLOW[警告]$NC 文件不存在,跳过删除: $file" - } - } - - # 清空指定文件夹内容 - Write-Host "$BLUE[调试]$NC 检查待清空文件夹: $folderToCleanContents" - if (Test-Path $folderToCleanContents) { - try { - # 获取子项进行删除,以避免删除 History 文件夹本身 - Get-ChildItem -Path $folderToCleanContents -Recurse | Remove-Item -Recurse -Force -ErrorAction Stop - Write-Host "$GREEN[成功]$NC 已清空文件夹内容: $folderToCleanContents" - } - catch { - Write-Host "$RED[错误]$NC 清空文件夹 $folderToCleanContents 内容失败: $($_.Exception.Message)" - } - } else { - Write-Host "$YELLOW[警告]$NC 文件夹不存在,跳过清空: $folderToCleanContents" - } - - # 删除指定文件夹及其内容 - Write-Host "$BLUE[调试]$NC 检查待删除文件夹: $folderToDeleteCompletely" - if (Test-Path $folderToDeleteCompletely) { - try { - Remove-Item -Path $folderToDeleteCompletely -Recurse -Force -ErrorAction Stop - Write-Host "$GREEN[成功]$NC 已删除文件夹: $folderToDeleteCompletely" - } - catch { - Write-Host "$RED[错误]$NC 删除文件夹 $folderToDeleteCompletely 失败: $($_.Exception.Message)" - } - } else { - Write-Host "$YELLOW[警告]$NC 文件夹不存在,跳过删除: $folderToDeleteCompletely" - } - - Write-Host "$GREEN[信息]$NC Cursor 初始化清理完成。" - Write-Host "" # 添加空行以改善输出格式 -} - -# 检查管理员权限 -function Test-Administrator { - $user = [Security.Principal.WindowsIdentity]::GetCurrent() - $principal = New-Object Security.Principal.WindowsPrincipal($user) - return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) -} - -if (-not (Test-Administrator)) { - Write-Host "$RED[错误]$NC 请以管理员身份运行此脚本" - Write-Host "请右键点击脚本,选择'以管理员身份运行'" - Read-Host "按回车键退出" - exit 1 -} - -# 显示 Logo -Clear-Host -Write-Host @" - - ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ - ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ - ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ - ██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ - ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ - ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ - -"@ -Write-Host "$BLUE================================$NC" -Write-Host "$GREEN Cursor 设备ID 修改工具 $NC" -Write-Host "$YELLOW 关注公众号【煎饼果子卷AI】 $NC" -Write-Host "$YELLOW 一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) $NC" -Write-Host "$YELLOW [重要提示] 本工具免费,如果对您有帮助,请关注公众号【煎饼果子卷AI】 $NC" -Write-Host "" -Write-Host "$YELLOW⚡ [小小广告] Cursor官网正规成品号:Pro¥65 | Pro+¥265 | Ultra¥888 独享账号/7天质保,WeChat:JavaRookie666 $NC" -Write-Host "$BLUE================================$NC" - -# 获取并显示 Cursor 版本 -function Get-CursorVersion { - try { - # 主要检测路径 - $packagePath = "$env:LOCALAPPDATA\\Programs\\cursor\\resources\\app\\package.json" - - if (Test-Path $packagePath) { - $packageJson = Get-Content $packagePath -Raw | ConvertFrom-Json - if ($packageJson.version) { - Write-Host "$GREEN[信息]$NC 当前安装的 Cursor 版本: v$($packageJson.version)" - return $packageJson.version - } - } - - # 备用路径检测 - $altPath = "$env:LOCALAPPDATA\\cursor\\resources\\app\\package.json" - if (Test-Path $altPath) { - $packageJson = Get-Content $altPath -Raw | ConvertFrom-Json - if ($packageJson.version) { - Write-Host "$GREEN[信息]$NC 当前安装的 Cursor 版本: v$($packageJson.version)" - return $packageJson.version - } - } - - Write-Host "$YELLOW[警告]$NC 无法检测到 Cursor 版本" - Write-Host "$YELLOW[提示]$NC 请确保 Cursor 已正确安装" - return $null - } - catch { - Write-Host "$RED[错误]$NC 获取 Cursor 版本失败: $_" - return $null - } -} - -# 获取并显示版本信息 -$cursorVersion = Get-CursorVersion -Write-Host "" - -Write-Host "$YELLOW[重要提示]$NC 最新的 1.0.x (以支持)" -Write-Host "" - -# 检查并关闭 Cursor 进程 -Write-Host "$GREEN[信息]$NC 检查 Cursor 进程..." - -function Get-ProcessDetails { - param($processName) - Write-Host "$BLUE[调试]$NC 正在获取 $processName 进程详细信息:" - Get-WmiObject Win32_Process -Filter "name='$processName'" | - Select-Object ProcessId, ExecutablePath, CommandLine | - Format-List -} - -# 定义最大重试次数和等待时间 -$MAX_RETRIES = 5 -$WAIT_TIME = 1 - -# 处理进程关闭 -function Close-CursorProcess { - param($processName) - - $process = Get-Process -Name $processName -ErrorAction SilentlyContinue - if ($process) { - Write-Host "$YELLOW[警告]$NC 发现 $processName 正在运行" - Get-ProcessDetails $processName - - Write-Host "$YELLOW[警告]$NC 尝试关闭 $processName..." - Stop-Process -Name $processName -Force - - $retryCount = 0 - while ($retryCount -lt $MAX_RETRIES) { - $process = Get-Process -Name $processName -ErrorAction SilentlyContinue - if (-not $process) { break } - - $retryCount++ - if ($retryCount -ge $MAX_RETRIES) { - Write-Host "$RED[错误]$NC 在 $MAX_RETRIES 次尝试后仍无法关闭 $processName" - Get-ProcessDetails $processName - Write-Host "$RED[错误]$NC 请手动关闭进程后重试" - Read-Host "按回车键退出" - exit 1 - } - Write-Host "$YELLOW[警告]$NC 等待进程关闭,尝试 $retryCount/$MAX_RETRIES..." - Start-Sleep -Seconds $WAIT_TIME - } - Write-Host "$GREEN[信息]$NC $processName 已成功关闭" - } -} - -# 关闭所有 Cursor 进程 -Close-CursorProcess "Cursor" -Close-CursorProcess "cursor" - -# 执行 Cursor 初始化清理 -# Cursor-初始化 - -# 创建备份目录 -if (-not (Test-Path $BACKUP_DIR)) { - New-Item -ItemType Directory -Path $BACKUP_DIR | Out-Null -} - -# 备份现有配置 -if (Test-Path $STORAGE_FILE) { - Write-Host "$GREEN[信息]$NC 正在备份配置文件..." - $backupName = "storage.json.backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')" - Copy-Item $STORAGE_FILE "$BACKUP_DIR\$backupName" -} - -# 生成新的 ID -Write-Host "$GREEN[信息]$NC 正在生成新的 ID..." - -# 在颜色定义后添加此函数 -function Get-RandomHex { - param ( - [int]$length - ) - - $bytes = New-Object byte[] ($length) - $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::new() - $rng.GetBytes($bytes) - $hexString = [System.BitConverter]::ToString($bytes) -replace '-','' - $rng.Dispose() - return $hexString -} - -# 改进 ID 生成函数 -function New-StandardMachineId { - $template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" - $result = $template -replace '[xy]', { - param($match) - $r = [Random]::new().Next(16) - $v = if ($match.Value -eq "x") { $r } else { ($r -band 0x3) -bor 0x8 } - return $v.ToString("x") - } - return $result -} - -# 在生成 ID 时使用新函数 -$MAC_MACHINE_ID = New-StandardMachineId -$UUID = [System.Guid]::NewGuid().ToString() -# 将 auth0|user_ 转换为字节数组的十六进制 -$prefixBytes = [System.Text.Encoding]::UTF8.GetBytes("auth0|user_") -$prefixHex = -join ($prefixBytes | ForEach-Object { '{0:x2}' -f $_ }) -# 生成32字节(64个十六进制字符)的随机数作为 machineId 的随机部分 -$randomPart = Get-RandomHex -length 32 -$MACHINE_ID = "$prefixHex$randomPart" -$SQM_ID = "{$([System.Guid]::NewGuid().ToString().ToUpper())}" - -# 在Update-MachineGuid函数前添加权限检查 -if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { - Write-Host "$RED[错误]$NC 请使用管理员权限运行此脚本" - Start-Process powershell "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs - exit -} - -function Update-MachineGuid { - try { - # 检查注册表路径是否存在,不存在则创建 - $registryPath = "HKLM:\SOFTWARE\Microsoft\Cryptography" - if (-not (Test-Path $registryPath)) { - Write-Host "$YELLOW[警告]$NC 注册表路径不存在: $registryPath,正在创建..." - New-Item -Path $registryPath -Force | Out-Null - Write-Host "$GREEN[信息]$NC 注册表路径创建成功" - } - - # 获取当前的 MachineGuid,如果不存在则使用空字符串作为默认值 - $originalGuid = "" - try { - $currentGuid = Get-ItemProperty -Path $registryPath -Name MachineGuid -ErrorAction SilentlyContinue - if ($currentGuid) { - $originalGuid = $currentGuid.MachineGuid - Write-Host "$GREEN[信息]$NC 当前注册表值:" - Write-Host "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography" - Write-Host " MachineGuid REG_SZ $originalGuid" - } else { - Write-Host "$YELLOW[警告]$NC MachineGuid 值不存在,将创建新值" - } - } catch { - Write-Host "$YELLOW[警告]$NC 获取 MachineGuid 失败: $($_.Exception.Message)" - } - - # 创建备份目录(如果不存在) - if (-not (Test-Path $BACKUP_DIR)) { - New-Item -ItemType Directory -Path $BACKUP_DIR -Force | Out-Null - } - - # 创建备份文件(仅当原始值存在时) - if ($originalGuid) { - $backupFile = "$BACKUP_DIR\MachineGuid_$(Get-Date -Format 'yyyyMMdd_HHmmss').reg" - $backupResult = Start-Process "reg.exe" -ArgumentList "export", "`"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography`"", "`"$backupFile`"" -NoNewWindow -Wait -PassThru - - if ($backupResult.ExitCode -eq 0) { - Write-Host "$GREEN[信息]$NC 注册表项已备份到:$backupFile" - } else { - Write-Host "$YELLOW[警告]$NC 备份创建失败,继续执行..." - } - } - - # 生成新GUID - $newGuid = [System.Guid]::NewGuid().ToString() - - # 更新或创建注册表值 - Set-ItemProperty -Path $registryPath -Name MachineGuid -Value $newGuid -Force -ErrorAction Stop - - # 验证更新 - $verifyGuid = (Get-ItemProperty -Path $registryPath -Name MachineGuid -ErrorAction Stop).MachineGuid - if ($verifyGuid -ne $newGuid) { - throw "注册表验证失败:更新后的值 ($verifyGuid) 与预期值 ($newGuid) 不匹配" - } - - Write-Host "$GREEN[信息]$NC 注册表更新成功:" - Write-Host "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography" - Write-Host " MachineGuid REG_SZ $newGuid" - return $true - } - catch { - Write-Host "$RED[错误]$NC 注册表操作失败:$($_.Exception.Message)" - - # 尝试恢复备份(如果存在) - if (($backupFile -ne $null) -and (Test-Path $backupFile)) { - Write-Host "$YELLOW[恢复]$NC 正在从备份恢复..." - $restoreResult = Start-Process "reg.exe" -ArgumentList "import", "`"$backupFile`"" -NoNewWindow -Wait -PassThru - - if ($restoreResult.ExitCode -eq 0) { - Write-Host "$GREEN[恢复成功]$NC 已还原原始注册表值" - } else { - Write-Host "$RED[错误]$NC 恢复失败,请手动导入备份文件:$backupFile" - } - } else { - Write-Host "$YELLOW[警告]$NC 未找到备份文件或备份创建失败,无法自动恢复" - } - return $false - } -} - -# 创建或更新配置文件 -Write-Host "$GREEN[信息]$NC 正在更新配置..." - -try { - # 检查配置文件是否存在 - if (-not (Test-Path $STORAGE_FILE)) { - Write-Host "$RED[错误]$NC 未找到配置文件: $STORAGE_FILE" - Write-Host "$YELLOW[提示]$NC 请先安装并运行一次 Cursor 后再使用此脚本" - Read-Host "按回车键退出" - exit 1 - } - - # 读取现有配置文件 - try { - $originalContent = Get-Content $STORAGE_FILE -Raw -Encoding UTF8 - - # 将 JSON 字符串转换为 PowerShell 对象 - $config = $originalContent | ConvertFrom-Json - - # 备份当前值 - $oldValues = @{ - 'machineId' = $config.'telemetry.machineId' - 'macMachineId' = $config.'telemetry.macMachineId' - 'devDeviceId' = $config.'telemetry.devDeviceId' - 'sqmId' = $config.'telemetry.sqmId' - } - - # 更新特定的值 - $config.'telemetry.machineId' = $MACHINE_ID - $config.'telemetry.macMachineId' = $MAC_MACHINE_ID - $config.'telemetry.devDeviceId' = $UUID - $config.'telemetry.sqmId' = $SQM_ID - - # 将更新后的对象转换回 JSON 并保存 - $updatedJson = $config | ConvertTo-Json -Depth 10 - [System.IO.File]::WriteAllText( - [System.IO.Path]::GetFullPath($STORAGE_FILE), - $updatedJson, - [System.Text.Encoding]::UTF8 - ) - Write-Host "$GREEN[信息]$NC 成功更新配置文件" - } catch { - # 如果出错,尝试恢复原始内容 - if ($originalContent) { - [System.IO.File]::WriteAllText( - [System.IO.Path]::GetFullPath($STORAGE_FILE), - $originalContent, - [System.Text.Encoding]::UTF8 - ) - } - throw "处理 JSON 失败: $_" - } - # 直接执行更新 MachineGuid,不再询问 - Update-MachineGuid - # 显示结果 - Write-Host "" - Write-Host "$GREEN[信息]$NC 已更新配置:" - Write-Host "$BLUE[调试]$NC machineId: $MACHINE_ID" - Write-Host "$BLUE[调试]$NC macMachineId: $MAC_MACHINE_ID" - Write-Host "$BLUE[调试]$NC devDeviceId: $UUID" - Write-Host "$BLUE[调试]$NC sqmId: $SQM_ID" - - # 显示文件树结构 - Write-Host "" - Write-Host "$GREEN[信息]$NC 文件结构:" - Write-Host "$BLUE$env:APPDATA\Cursor\User$NC" - Write-Host "├── globalStorage" - Write-Host "│ ├── storage.json (已修改)" - Write-Host "│ └── backups" - - # 列出备份文件 - $backupFiles = Get-ChildItem "$BACKUP_DIR\*" -ErrorAction SilentlyContinue - if ($backupFiles) { - foreach ($file in $backupFiles) { - Write-Host "│ └── $($file.Name)" - } - } else { - Write-Host "│ └── (空)" - } - - # 显示公众号信息 - Write-Host "" - Write-Host "$GREEN================================$NC" - Write-Host "$YELLOW 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识(脚本免费、关注公众号加群有更多技巧和大佬) $NC" - Write-Host "$GREEN================================$NC" - Write-Host "" - Write-Host "$GREEN[信息]$NC 请重启 Cursor 以应用新的配置" - Write-Host "" - - # 询问是否要禁用自动更新 - Write-Host "" - Write-Host "$YELLOW[询问]$NC 是否要禁用 Cursor 自动更新功能?" - Write-Host "0) 否 - 保持默认设置 (按回车键)" - Write-Host "1) 是 - 禁用自动更新" - $choice = Read-Host "请输入选项 (0)" - - if ($choice -eq "1") { - Write-Host "" - Write-Host "$GREEN[信息]$NC 正在处理自动更新..." - $updaterPath = "$env:LOCALAPPDATA\cursor-updater" - - # 定义手动设置教程 - function Show-ManualGuide { - Write-Host "" - Write-Host "$YELLOW[警告]$NC 自动设置失败,请尝试手动操作:" - Write-Host "$YELLOW手动禁用更新步骤:$NC" - Write-Host "1. 以管理员身份打开 PowerShell" - Write-Host "2. 复制粘贴以下命令:" - Write-Host "$BLUE命令1 - 删除现有目录(如果存在):$NC" - Write-Host "Remove-Item -Path `"$updaterPath`" -Force -Recurse -ErrorAction SilentlyContinue" - Write-Host "" - Write-Host "$BLUE命令2 - 创建阻止文件:$NC" - Write-Host "New-Item -Path `"$updaterPath`" -ItemType File -Force | Out-Null" - Write-Host "" - Write-Host "$BLUE命令3 - 设置只读属性:$NC" - Write-Host "Set-ItemProperty -Path `"$updaterPath`" -Name IsReadOnly -Value `$true" - Write-Host "" - Write-Host "$BLUE命令4 - 设置权限(可选):$NC" - Write-Host "icacls `"$updaterPath`" /inheritance:r /grant:r `"`$($env:USERNAME):(R)`"" - Write-Host "" - Write-Host "$YELLOW验证方法:$NC" - Write-Host "1. 运行命令:Get-ItemProperty `"$updaterPath`"" - Write-Host "2. 确认 IsReadOnly 属性为 True" - Write-Host "3. 运行命令:icacls `"$updaterPath`"" - Write-Host "4. 确认只有读取权限" - Write-Host "" - Write-Host "$YELLOW[提示]$NC 完成后请重启 Cursor" - } - - try { - # 检查cursor-updater是否存在 - if (Test-Path $updaterPath) { - # 如果是文件,说明已经创建了阻止更新 - if ((Get-Item $updaterPath) -is [System.IO.FileInfo]) { - Write-Host "$GREEN[信息]$NC 已创建阻止更新文件,无需再次阻止" - return - } - # 如果是目录,尝试删除 - else { - try { - Remove-Item -Path $updaterPath -Force -Recurse -ErrorAction Stop - Write-Host "$GREEN[信息]$NC 成功删除 cursor-updater 目录" - } - catch { - Write-Host "$RED[错误]$NC 删除 cursor-updater 目录失败" - Show-ManualGuide - return - } - } - } - - # 创建阻止文件 - try { - New-Item -Path $updaterPath -ItemType File -Force -ErrorAction Stop | Out-Null - Write-Host "$GREEN[信息]$NC 成功创建阻止文件" - } - catch { - Write-Host "$RED[错误]$NC 创建阻止文件失败" - Show-ManualGuide - return - } - - # 设置文件权限 - try { - # 设置只读属性 - Set-ItemProperty -Path $updaterPath -Name IsReadOnly -Value $true -ErrorAction Stop - - # 使用 icacls 设置权限 - $result = Start-Process "icacls.exe" -ArgumentList "`"$updaterPath`" /inheritance:r /grant:r `"$($env:USERNAME):(R)`"" -Wait -NoNewWindow -PassThru - if ($result.ExitCode -ne 0) { - throw "icacls 命令失败" - } - - Write-Host "$GREEN[信息]$NC 成功设置文件权限" - } - catch { - Write-Host "$RED[错误]$NC 设置文件权限失败" - Show-ManualGuide - return - } - - # 验证设置 - try { - $fileInfo = Get-ItemProperty $updaterPath - if (-not $fileInfo.IsReadOnly) { - Write-Host "$RED[错误]$NC 验证失败:文件权限设置可能未生效" - Show-ManualGuide - return - } - } - catch { - Write-Host "$RED[错误]$NC 验证设置失败" - Show-ManualGuide - return - } - - Write-Host "$GREEN[信息]$NC 成功禁用自动更新" - } - catch { - Write-Host "$RED[错误]$NC 发生未知错误: $_" - Show-ManualGuide - } - } - else { - Write-Host "$GREEN[信息]$NC 保持默认设置,不进行更改" - } - - # 保留有效的注册表更新 - Update-MachineGuid - -} catch { - Write-Host "$RED[错误]$NC 主要操作失败: $_" - Write-Host "$YELLOW[尝试]$NC 使用备选方法..." - - try { - # 备选方法:使用 Add-Content - $tempFile = [System.IO.Path]::GetTempFileName() - $config | ConvertTo-Json | Set-Content -Path $tempFile -Encoding UTF8 - Copy-Item -Path $tempFile -Destination $STORAGE_FILE -Force - Remove-Item -Path $tempFile - Write-Host "$GREEN[信息]$NC 使用备选方法成功写入配置" - } catch { - Write-Host "$RED[错误]$NC 所有尝试都失败了" - Write-Host "错误详情: $_" - Write-Host "目标文件: $STORAGE_FILE" - Write-Host "请确保您有足够的权限访问该文件" - Read-Host "按回车键退出" - exit 1 - } -} - -Write-Host "" -Read-Host "按回车键退出" -exit 0 - -# 在文件写入部分修改 -function Write-ConfigFile { - param($config, $filePath) - - try { - # 使用 UTF8 无 BOM 编码 - $utf8NoBom = New-Object System.Text.UTF8Encoding $false - $jsonContent = $config | ConvertTo-Json -Depth 10 - - # 统一使用 LF 换行符 - $jsonContent = $jsonContent.Replace("`r`n", "`n") - - [System.IO.File]::WriteAllText( - [System.IO.Path]::GetFullPath($filePath), - $jsonContent, - $utf8NoBom - ) - - Write-Host "$GREEN[信息]$NC 成功写入配置文件(UTF8 无 BOM)" - } - catch { - throw "写入配置文件失败: $_" - } -} \ No newline at end of file