|
| 1 | +# 设置输出编码为 UTF-8 |
| 2 | +$OutputEncoding = [System.Text.Encoding]::UTF8 |
| 3 | +[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 |
| 4 | + |
| 5 | +# 颜色定义 |
| 6 | +$RED = "`e[31m" |
| 7 | +$GREEN = "`e[32m" |
| 8 | +$YELLOW = "`e[33m" |
| 9 | +$BLUE = "`e[34m" |
| 10 | +$NC = "`e[0m" |
| 11 | + |
| 12 | +# 配置文件路径 |
| 13 | +$STORAGE_FILE = "$env:APPDATA\Cursor\User\globalStorage\storage.json" |
| 14 | +$BACKUP_DIR = "$env:APPDATA\Cursor\User\globalStorage\backups" |
| 15 | + |
| 16 | +# 检查管理员权限 |
| 17 | +function Test-Administrator { |
| 18 | + $user = [Security.Principal.WindowsIdentity]::GetCurrent() |
| 19 | + $principal = New-Object Security.Principal.WindowsPrincipal($user) |
| 20 | + return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) |
| 21 | +} |
| 22 | + |
| 23 | +if (-not (Test-Administrator)) { |
| 24 | + Write-Host "$RED[错误]$NC 请以管理员身份运行此脚本" |
| 25 | + Write-Host "请右键点击脚本,选择'以管理员身份运行'" |
| 26 | + Read-Host "按回车键退出" |
| 27 | + exit 1 |
| 28 | +} |
| 29 | + |
| 30 | +# 显示 Logo |
| 31 | +Clear-Host |
| 32 | +Write-Host @" |
| 33 | +
|
| 34 | + ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ |
| 35 | + ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ |
| 36 | + ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ |
| 37 | + ██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗ |
| 38 | + ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ |
| 39 | + ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ |
| 40 | +
|
| 41 | +"@ |
| 42 | +Write-Host "$BLUE================================$NC" |
| 43 | +Write-Host "$GREEN Cursor ID 修改工具 $NC" |
| 44 | +Write-Host "$BLUE================================$NC" |
| 45 | +Write-Host "" |
| 46 | + |
| 47 | +# 检查并关闭 Cursor 进程 |
| 48 | +Write-Host "$GREEN[信息]$NC 检查 Cursor 进程..." |
| 49 | + |
| 50 | +function Get-ProcessDetails { |
| 51 | + param($processName) |
| 52 | + Write-Host "$BLUE[调试]$NC 正在获取 $processName 进程详细信息:" |
| 53 | + Get-WmiObject Win32_Process -Filter "name='$processName'" | |
| 54 | + Select-Object ProcessId, ExecutablePath, CommandLine | |
| 55 | + Format-List |
| 56 | +} |
| 57 | + |
| 58 | +# 定义最大重试次数和等待时间 |
| 59 | +$MAX_RETRIES = 5 |
| 60 | +$WAIT_TIME = 1 |
| 61 | + |
| 62 | +# 处理进程关闭 |
| 63 | +function Close-CursorProcess { |
| 64 | + param($processName) |
| 65 | + |
| 66 | + $process = Get-Process -Name $processName -ErrorAction SilentlyContinue |
| 67 | + if ($process) { |
| 68 | + Write-Host "$YELLOW[警告]$NC 发现 $processName 正在运行" |
| 69 | + Get-ProcessDetails $processName |
| 70 | + |
| 71 | + Write-Host "$YELLOW[警告]$NC 尝试关闭 $processName..." |
| 72 | + Stop-Process -Name $processName -Force |
| 73 | + |
| 74 | + $retryCount = 0 |
| 75 | + while ($retryCount -lt $MAX_RETRIES) { |
| 76 | + $process = Get-Process -Name $processName -ErrorAction SilentlyContinue |
| 77 | + if (-not $process) { break } |
| 78 | + |
| 79 | + $retryCount++ |
| 80 | + if ($retryCount -ge $MAX_RETRIES) { |
| 81 | + Write-Host "$RED[错误]$NC 在 $MAX_RETRIES 次尝试后仍无法关闭 $processName" |
| 82 | + Get-ProcessDetails $processName |
| 83 | + Write-Host "$RED[错误]$NC 请手动关闭进程后重试" |
| 84 | + Read-Host "按回车键退出" |
| 85 | + exit 1 |
| 86 | + } |
| 87 | + Write-Host "$YELLOW[警告]$NC 等待进程关闭,尝试 $retryCount/$MAX_RETRIES..." |
| 88 | + Start-Sleep -Seconds $WAIT_TIME |
| 89 | + } |
| 90 | + Write-Host "$GREEN[信息]$NC $processName 已成功关闭" |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +# 关闭所有 Cursor 进程 |
| 95 | +Close-CursorProcess "Cursor" |
| 96 | +Close-CursorProcess "cursor" |
| 97 | + |
| 98 | +# 创建备份目录 |
| 99 | +if (-not (Test-Path $BACKUP_DIR)) { |
| 100 | + New-Item -ItemType Directory -Path $BACKUP_DIR | Out-Null |
| 101 | +} |
| 102 | + |
| 103 | +# 备份现有配置 |
| 104 | +if (Test-Path $STORAGE_FILE) { |
| 105 | + Write-Host "$GREEN[信息]$NC 正在备份配置文件..." |
| 106 | + $backupName = "storage.json.backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')" |
| 107 | + Copy-Item $STORAGE_FILE "$BACKUP_DIR\$backupName" |
| 108 | +} |
| 109 | + |
| 110 | +# 生成新的 ID |
| 111 | +Write-Host "$GREEN[信息]$NC 正在生成新的 ID..." |
| 112 | + |
| 113 | +# 生成随机字节数组并转换为十六进制字符串的函数 |
| 114 | +function Get-RandomHex { |
| 115 | + param ( |
| 116 | + [int]$length |
| 117 | + ) |
| 118 | + $bytes = New-Object byte[] $length |
| 119 | + $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::new() |
| 120 | + $rng.GetBytes($bytes) |
| 121 | + $rng.Dispose() |
| 122 | + return -join ($bytes | ForEach-Object { '{0:x2}' -f $_ }) |
| 123 | +} |
| 124 | + |
| 125 | +$UUID = [System.Guid]::NewGuid().ToString() |
| 126 | +# 将 auth0|user_ 转换为字节数组的十六进制 |
| 127 | +$prefixBytes = [System.Text.Encoding]::UTF8.GetBytes("auth0|user_") |
| 128 | +$prefixHex = -join ($prefixBytes | ForEach-Object { '{0:x2}' -f $_ }) |
| 129 | +# 生成32字节(64个十六进制字符)的随机数作为 machineId 的随机部分 |
| 130 | +$randomPart = Get-RandomHex -length 32 |
| 131 | +$MACHINE_ID = "$prefixHex$randomPart" |
| 132 | +$MAC_MACHINE_ID = Get-RandomHex -length 32 |
| 133 | +$SQM_ID = "{$([System.Guid]::NewGuid().ToString().ToUpper())}" |
| 134 | + |
| 135 | +# 创建或更新配置文件 |
| 136 | +Write-Host "$GREEN[信息]$NC 正在更新配置..." |
| 137 | + |
| 138 | +try { |
| 139 | + # 确保目录存在 |
| 140 | + $storageDir = Split-Path $STORAGE_FILE -Parent |
| 141 | + if (-not (Test-Path $storageDir)) { |
| 142 | + New-Item -ItemType Directory -Path $storageDir -Force | Out-Null |
| 143 | + } |
| 144 | + |
| 145 | + # 写入配置 |
| 146 | + $config = @{ |
| 147 | + 'telemetry.machineId' = $MACHINE_ID |
| 148 | + 'telemetry.macMachineId' = $MAC_MACHINE_ID |
| 149 | + 'telemetry.devDeviceId' = $UUID |
| 150 | + 'telemetry.sqmId' = $SQM_ID |
| 151 | + } |
| 152 | + |
| 153 | + # 使用 System.IO.File 方法写入文件 |
| 154 | + try { |
| 155 | + $jsonContent = $config | ConvertTo-Json |
| 156 | + [System.IO.File]::WriteAllText( |
| 157 | + [System.IO.Path]::GetFullPath($STORAGE_FILE), |
| 158 | + $jsonContent, |
| 159 | + [System.Text.Encoding]::UTF8 |
| 160 | + ) |
| 161 | + Write-Host "$GREEN[信息]$NC 成功写入配置文件" |
| 162 | + } catch { |
| 163 | + throw "写入文件失败: $_" |
| 164 | + } |
| 165 | + |
| 166 | + # 尝试设置文件权限 |
| 167 | + try { |
| 168 | + # 使用当前用户名和域名 |
| 169 | + $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent() |
| 170 | + $userAccount = "$($env:USERDOMAIN)\$($env:USERNAME)" |
| 171 | + |
| 172 | + # 创建新的访问控制列表 |
| 173 | + $acl = New-Object System.Security.AccessControl.FileSecurity |
| 174 | + |
| 175 | + # 添加当前用户的完全控制权限 |
| 176 | + $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule( |
| 177 | + $userAccount, # 使用域名\用户名格式 |
| 178 | + [System.Security.AccessControl.FileSystemRights]::FullControl, |
| 179 | + [System.Security.AccessControl.InheritanceFlags]::None, |
| 180 | + [System.Security.AccessControl.PropagationFlags]::None, |
| 181 | + [System.Security.AccessControl.AccessControlType]::Allow |
| 182 | + ) |
| 183 | + |
| 184 | + try { |
| 185 | + $acl.AddAccessRule($accessRule) |
| 186 | + Set-Acl -Path $STORAGE_FILE -AclObject $acl -ErrorAction Stop |
| 187 | + Write-Host "$GREEN[信息]$NC 成功设置文件权限" |
| 188 | + } catch { |
| 189 | + # 如果第一种方法失败,尝试使用 icacls |
| 190 | + Write-Host "$YELLOW[警告]$NC 使用备选方法设置权限..." |
| 191 | + $result = Start-Process "icacls.exe" -ArgumentList "`"$STORAGE_FILE`" /grant `"$($env:USERNAME):(F)`"" -Wait -NoNewWindow -PassThru |
| 192 | + if ($result.ExitCode -eq 0) { |
| 193 | + Write-Host "$GREEN[信息]$NC 成功使用 icacls 设置文件权限" |
| 194 | + } else { |
| 195 | + Write-Host "$YELLOW[警告]$NC 设置文件权限失败,但文件已写入成功" |
| 196 | + } |
| 197 | + } |
| 198 | + } catch { |
| 199 | + Write-Host "$YELLOW[警告]$NC 设置文件权限失败: $_" |
| 200 | + Write-Host "$YELLOW[警告]$NC 尝试使用 icacls 命令..." |
| 201 | + try { |
| 202 | + $result = Start-Process "icacls.exe" -ArgumentList "`"$STORAGE_FILE`" /grant `"$($env:USERNAME):(F)`"" -Wait -NoNewWindow -PassThru |
| 203 | + if ($result.ExitCode -eq 0) { |
| 204 | + Write-Host "$GREEN[信息]$NC 成功使用 icacls 设置文件权限" |
| 205 | + } else { |
| 206 | + Write-Host "$YELLOW[警告]$NC 所有权限设置方法都失败,但文件已写入成功" |
| 207 | + } |
| 208 | + } catch { |
| 209 | + Write-Host "$YELLOW[警告]$NC icacls 命令失败: $_" |
| 210 | + } |
| 211 | + } |
| 212 | + |
| 213 | +} catch { |
| 214 | + Write-Host "$RED[错误]$NC 主要操作失败: $_" |
| 215 | + Write-Host "$YELLOW[尝试]$NC 使用备选方法..." |
| 216 | + |
| 217 | + try { |
| 218 | + # 备选方法:使用 Add-Content |
| 219 | + $tempFile = [System.IO.Path]::GetTempFileName() |
| 220 | + $config | ConvertTo-Json | Set-Content -Path $tempFile -Encoding UTF8 |
| 221 | + Copy-Item -Path $tempFile -Destination $STORAGE_FILE -Force |
| 222 | + Remove-Item -Path $tempFile |
| 223 | + Write-Host "$GREEN[信息]$NC 使用备选方法成功写入配置" |
| 224 | + } catch { |
| 225 | + Write-Host "$RED[错误]$NC 所有尝试都失败了" |
| 226 | + Write-Host "错误详情: $_" |
| 227 | + Write-Host "目标文件: $STORAGE_FILE" |
| 228 | + Write-Host "请确保您有足够的权限访问该文件" |
| 229 | + Read-Host "按回车键退出" |
| 230 | + exit 1 |
| 231 | + } |
| 232 | +} |
| 233 | + |
| 234 | +# 显示结果 |
| 235 | +Write-Host "" |
| 236 | +Write-Host "$GREEN[信息]$NC 已更新配置:" |
| 237 | +Write-Host "$BLUE[调试]$NC machineId: $MACHINE_ID" |
| 238 | +Write-Host "$BLUE[调试]$NC macMachineId: $MAC_MACHINE_ID" |
| 239 | +Write-Host "$BLUE[调试]$NC devDeviceId: $UUID" |
| 240 | +Write-Host "$BLUE[调试]$NC sqmId: $SQM_ID" |
| 241 | + |
| 242 | +# 显示文件树结构 |
| 243 | +Write-Host "" |
| 244 | +Write-Host "$GREEN[信息]$NC 文件结构:" |
| 245 | +Write-Host "$BLUE$env:APPDATA\Cursor\User$NC" |
| 246 | +Write-Host "├── globalStorage" |
| 247 | +Write-Host "│ ├── storage.json (已修改)" |
| 248 | +Write-Host "│ └── backups" |
| 249 | + |
| 250 | +# 列出备份文件 |
| 251 | +$backupFiles = Get-ChildItem "$BACKUP_DIR\*" -ErrorAction SilentlyContinue |
| 252 | +if ($backupFiles) { |
| 253 | + foreach ($file in $backupFiles) { |
| 254 | + Write-Host "│ └── $($file.Name)" |
| 255 | + } |
| 256 | +} else { |
| 257 | + Write-Host "│ └── (空)" |
| 258 | +} |
| 259 | + |
| 260 | +# 显示公众号信息 |
| 261 | +Write-Host "" |
| 262 | +Write-Host "$GREEN================================$NC" |
| 263 | +Write-Host "$YELLOW 关注公众号【煎饼果子卷AI】一起交流更多Cursor技巧和AI知识 $NC" |
| 264 | +Write-Host "$GREEN================================$NC" |
| 265 | +Write-Host "" |
| 266 | +Write-Host "$GREEN[信息]$NC 请重启 Cursor 以应用新的配置" |
| 267 | +Write-Host "" |
| 268 | + |
| 269 | +# 询问是否要禁用自动更新 |
| 270 | +Write-Host "" |
| 271 | +Write-Host "$YELLOW[询问]$NC 是否要禁用 Cursor 自动更新功能?" |
| 272 | +Write-Host "0) 否 - 保持默认设置 (按回车键)" |
| 273 | +Write-Host "1) 是 - 禁用自动更新" |
| 274 | +$choice = Read-Host "请输入选项 (1 或直接回车)" |
| 275 | + |
| 276 | +if ($choice -eq "1") { |
| 277 | + Write-Host "" |
| 278 | + Write-Host "$GREEN[信息]$NC 正在处理自动更新..." |
| 279 | + $updaterPath = "$env:LOCALAPPDATA\cursor-updater" |
| 280 | + |
| 281 | + if (Test-Path $updaterPath) { |
| 282 | + try { |
| 283 | + # 强制删除目录 |
| 284 | + Remove-Item -Path $updaterPath -Force -Recurse -ErrorAction Stop |
| 285 | + Write-Host "$GREEN[信息]$NC 成功删除 cursor-updater 目录" |
| 286 | + |
| 287 | + # 创建同名文件 |
| 288 | + New-Item -Path $updaterPath -ItemType File -Force | Out-Null |
| 289 | + Write-Host "$GREEN[信息]$NC 成功创建阻止文件" |
| 290 | + } |
| 291 | + catch { |
| 292 | + Write-Host "$RED[错误]$NC 处理 cursor-updater 时出错: $_" |
| 293 | + } |
| 294 | + } |
| 295 | + else { |
| 296 | + # 直接创建阻止文件 |
| 297 | + New-Item -Path $updaterPath -ItemType File -Force | Out-Null |
| 298 | + Write-Host "$GREEN[信息]$NC 成功创建阻止文件" |
| 299 | + } |
| 300 | +} |
| 301 | +elseif ($choice -ne "") { |
| 302 | + Write-Host "$YELLOW[信息]$NC 保持默认设置,不进行更改" |
| 303 | +} |
| 304 | +else { |
| 305 | + Write-Host "$YELLOW[信息]$NC 保持默认设置,不进行更改" |
| 306 | +} |
| 307 | + |
| 308 | + |
| 309 | + |
| 310 | +Read-Host "按回车键退出" |
| 311 | +exit 0 |
0 commit comments