Browse Source
chore(scripts): 删除 Cursor 免费试用重置脚本
chore(scripts): 删除 Cursor 免费试用重置脚本
- 移除了 macOS 平台下用于重置 Cursor 编辑器免费试用期的 shell 脚本 - 该脚本包含修改应用程序文件、重置配置及权限修复等功能 - 脚本文件路径为 scripts/run/cursor_mac_free_trial_reset.sh - 此变更不影响其他平台或功能的正常使用
3 changed files with 0 additions and 2696 deletions
-
1401scripts/run/cursor_mac_free_trial_reset.sh
-
688scripts/run/cursor_mac_id_modifier_new.sh
-
607scripts/run/cursor_win_id_modifier_old.ps1
1401
scripts/run/cursor_mac_free_trial_reset.sh
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -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 "$@" |
|
||||
@ -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 "写入配置文件失败: $_" |
|
||||
} |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue