v3.2.6 稳定版本备份

This commit is contained in:
huangzhenpc
2025-02-12 13:20:06 +08:00
parent c2e3c99b8a
commit 6281f86743
14 changed files with 2197 additions and 141 deletions

View File

@@ -1,8 +1,12 @@
import os
import winreg
import logging
import shutil
from pathlib import Path
import uuid
from datetime import datetime
import json
import hashlib
class CursorRegistry:
"""Cursor注册表操作工具类"""
@@ -10,53 +14,61 @@ class CursorRegistry:
def __init__(self):
self.cursor_path = Path(os.path.expanduser("~")) / "AppData" / "Local" / "Programs" / "Cursor"
self.app_path = self.cursor_path / "resources" / "app"
self.machine_guid_path = r"SOFTWARE\Microsoft\Cryptography"
self.machine_guid_name = "MachineGuid"
def refresh_registry(self) -> bool:
"""刷新注册表
def update_machine_guid(self) -> bool:
"""更新系统的 MachineGuid
Returns:
bool: 是否成功
"""
try:
# 生成新的GUID
# 生成新的 GUID
new_guid = str(uuid.uuid4())
registry_path = r"SOFTWARE\Microsoft\Cryptography"
# 修改 MachineGuid
try:
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, self.machine_guid_path, 0, winreg.KEY_ALL_ACCESS) as key:
winreg.SetValueEx(key, self.machine_guid_name, 0, winreg.REG_SZ, new_guid)
logging.info(f"更新 MachineGuid 成功: {new_guid}")
except Exception as e:
logging.error(f"更新 MachineGuid 失败: {str(e)}")
return False
# 获取Cursor安装路径
cursor_exe = self.cursor_path / "Cursor.exe"
if not cursor_exe.exists():
logging.error("未找到Cursor.exe")
return False
# 使用管理员权限打开注册表项
key = None
try:
# 先尝试直接打开读取权限
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
winreg.KEY_READ | winreg.KEY_WOW64_64KEY)
# 读取原始值并备份
original_guid = winreg.QueryValueEx(key, "MachineGuid")[0]
winreg.CloseKey(key)
# 备份原始 MachineGuid
backup_dir = Path(os.getenv('APPDATA')) / "Cursor" / "User" / "globalStorage" / "backups"
backup_dir.mkdir(parents=True, exist_ok=True)
backup_name = f"MachineGuid.backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
with open(backup_dir / backup_name, 'w', encoding='utf-8') as f:
f.write(original_guid)
logging.info(f"备份 MachineGuid 到: {backup_name}")
# 重新打开写入权限
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY)
except WindowsError:
# 如果失败,尝试以管理员权限运行
import ctypes
if ctypes.windll.shell32.IsUserAnAdmin() == 0:
logging.warning("需要管理员权限来修改 MachineGuid")
return False
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
winreg.KEY_ALL_ACCESS | winreg.KEY_WOW64_64KEY)
# 刷新注册表项
try:
# 打开HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\Cursor
key_path = r"Software\Classes\Directory\Background\shell\Cursor"
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path, 0, winreg.KEY_WRITE) as key:
winreg.SetValueEx(key, "Icon", 0, winreg.REG_SZ, str(cursor_exe))
# 打开command子键
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path + r"\command", 0, winreg.KEY_WRITE) as key:
winreg.SetValueEx(key, "", 0, winreg.REG_SZ, f'"{str(cursor_exe)}" "%V"')
logging.info("注册表刷新成功")
# 设置新的 GUID
winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
winreg.CloseKey(key)
logging.info(f"更新系统 MachineGuid 成功: {new_guid}")
return True
except WindowsError as e:
logging.error(f"刷新注册表失败: {str(e)}")
logging.error(f"更新系统 MachineGuid 失败: {str(e)}")
return False
except Exception as e:
logging.error(f"刷新注册表失败: {str(e)}")
logging.error(f"更新 MachineGuid 过程出错: {str(e)}")
return False
def clean_registry(self) -> bool:
@@ -66,21 +78,149 @@ class CursorRegistry:
bool: 是否成功
"""
try:
# 删除注册表项
try:
key_path = r"Software\Classes\Directory\Background\shell\Cursor"
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, key_path + r"\command")
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, key_path)
logging.info("注册表清理成功")
return True
except WindowsError as e:
if e.winerror == 2: # 找不到注册表项
logging.info("注册表项不存在,无需清理")
return True
logging.error(f"清理注册表失败: {str(e)}")
return False
# 需要清理的注册表路径列表
registry_paths = [
r"Software\Classes\Directory\Background\shell\Cursor\command",
r"Software\Classes\Directory\Background\shell\Cursor",
r"Software\Cursor\Auth",
r"Software\Cursor\Updates",
r"Software\Cursor"
]
for path in registry_paths:
try:
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, path)
logging.info(f"删除注册表项成功: {path}")
except WindowsError as e:
if e.winerror == 2: # 找不到注册表项
logging.info(f"注册表项不存在,无需清理: {path}")
else:
logging.error(f"清理注册表失败: {path}, 错误: {str(e)}")
# 更新系统 MachineGuid
self.update_machine_guid()
return True
except Exception as e:
logging.error(f"清理注册表过程出错: {str(e)}")
return False
def clean_cursor_files(self) -> bool:
"""清理Cursor相关的文件和目录但保留重要的配置和历史记录"""
try:
local_app_data = Path(os.getenv('LOCALAPPDATA'))
app_data = Path(os.getenv('APPDATA'))
# 需要备份的文件
storage_path = app_data / "Cursor" / "User" / "globalStorage" / "storage.json"
backup_dir = app_data / "Cursor" / "User" / "globalStorage" / "backups"
global_storage_dir = app_data / "Cursor" / "User" / "globalStorage"
# 如果存在 storage.json先备份
if storage_path.exists():
# 确保备份目录存在
backup_dir.mkdir(parents=True, exist_ok=True)
# 备份 storage.json
backup_name = f"storage.json.backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
shutil.copy2(storage_path, backup_dir / backup_name)
logging.info(f"备份 storage.json 到: {backup_name}")
# 备份 global_storage 目录中的其他重要文件
if global_storage_dir.exists():
for item in global_storage_dir.iterdir():
if item.name != "storage.json" and item.name != "backups":
try:
backup_item_dir = backup_dir / f"other_files_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
backup_item_dir.mkdir(exist_ok=True)
if item.is_file():
shutil.copy2(item, backup_item_dir / item.name)
logging.info(f"备份文件: {item.name}")
elif item.is_dir():
shutil.copytree(item, backup_item_dir / item.name)
logging.info(f"备份目录: {item.name}")
except Exception as e:
logging.error(f"备份 {item} 失败: {str(e)}")
# 读取当前内容
with open(storage_path, "r", encoding="utf-8") as f:
storage_data = json.load(f)
# 只修改 machineId保持其他配置不变
if "telemetry.machineId" in storage_data:
# 生成新的 machineId
new_machine_id = hashlib.sha256(str(uuid.uuid4()).encode()).hexdigest()
storage_data["telemetry.machineId"] = new_machine_id
logging.info(f"更新 machineId: {new_machine_id}")
# 保存修改后的内容
with open(storage_path, "w", encoding="utf-8") as f:
json.dump(storage_data, f, indent=2)
# 处理 updater 目录
updater_path = local_app_data / "cursor-updater"
try:
# 如果是目录,则删除
if updater_path.is_dir():
shutil.rmtree(str(updater_path))
logging.info("删除 updater 目录成功")
# 如果是文件,则删除
if updater_path.is_file():
updater_path.unlink()
logging.info("删除 updater 文件成功")
# 创建同名空文件来阻止更新
updater_path.touch()
logging.info("创建 updater 空文件成功")
except Exception as e:
logging.error(f"处理 updater 文件失败: {str(e)}")
# 只清理缓存相关的路径
paths_to_clean = [
local_app_data / "Cursor" / "Cache"
]
for path in paths_to_clean:
try:
if path.is_dir():
shutil.rmtree(str(path), ignore_errors=True)
logging.info(f"删除目录成功: {path}")
elif path.exists():
path.unlink()
logging.info(f"删除文件成功: {path}")
except Exception as e:
logging.error(f"清理文件/目录失败: {path}, 错误: {str(e)}")
# 修复 Cursor 启动配置
self.fix_cursor_startup()
return True
except Exception as e:
logging.error(f"清理文件过程出错: {str(e)}")
return False
def fix_cursor_startup(self) -> bool:
"""修复 Cursor 启动警告"""
try:
# 1. 修改 package.json 中的更新相关配置
if self.app_path.exists():
package_json = self.app_path / "package.json"
if package_json.exists():
with open(package_json, "r", encoding="utf-8") as f:
data = json.load(f)
# 只修改更新相关配置,与 GitHub 脚本保持一致
data["updateUrl"] = "" # 清空更新 URL
data["disableUpdate"] = True # 禁用更新
with open(package_json, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
logging.info("已修复 Cursor 启动配置")
return True
except Exception as e:
logging.error(f"修复 Cursor 启动配置失败: {str(e)}")
return False