feat(v3.4.7): 重构重置功能和优化重启逻辑
1. 新增 CursorResetter 类,完整封装 cursor_win_id_modifier.ps1 的核心功能 2. 优化 AccountSwitcher 的重启逻辑,避免重复重启 3. 改进进程管理,移除 wmi 依赖,使用 tasklist 替代 4. 提升代码可维护性,后续只需更新 CursorResetter 即可适配脚本变更
This commit is contained in:
@@ -11,7 +11,8 @@ class Config:
|
||||
self.api_endpoints = {
|
||||
"activate": f"{self.base_url}/admin/api.member/activate",
|
||||
"status": f"{self.base_url}/admin/api.member/status",
|
||||
"get_unused": f"{self.base_url}/admin/api.account/getUnused"
|
||||
"get_unused": f"{self.base_url}/admin/api.account/getUnused",
|
||||
"heartbeat": f"{self.base_url}/admin/api.account/heartbeat"
|
||||
}
|
||||
self.config_dir = Path(os.path.expanduser("~")) / ".cursor_switcher"
|
||||
self.config_file = self.config_dir / "config.json"
|
||||
|
||||
@@ -7,6 +7,8 @@ import uuid
|
||||
from datetime import datetime
|
||||
import json
|
||||
import hashlib
|
||||
import ctypes
|
||||
from typing import Optional
|
||||
|
||||
class CursorRegistry:
|
||||
"""Cursor注册表操作工具类"""
|
||||
@@ -14,61 +16,115 @@ 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.backup_dir = Path(os.getenv('APPDATA')) / "Cursor" / "User" / "globalStorage" / "backups"
|
||||
|
||||
def get_random_hex(self, length: int) -> str:
|
||||
"""生成安全的随机十六进制字符串
|
||||
|
||||
Args:
|
||||
length: 需要生成的字节长度
|
||||
|
||||
Returns:
|
||||
str: 十六进制字符串
|
||||
"""
|
||||
import secrets
|
||||
return secrets.token_hex(length)
|
||||
|
||||
def new_standard_machine_id(self) -> str:
|
||||
"""生成标准格式的机器ID
|
||||
|
||||
Returns:
|
||||
str: 标准格式的机器ID
|
||||
"""
|
||||
template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
||||
|
||||
def replace_char(match):
|
||||
import random
|
||||
r = random.randint(0, 15)
|
||||
v = r if match == 'x' else (r & 0x3 | 0x8)
|
||||
return hex(v)[2:]
|
||||
|
||||
return ''.join(replace_char(c) for c in template)
|
||||
|
||||
def is_admin(self) -> bool:
|
||||
"""检查是否具有管理员权限
|
||||
|
||||
Returns:
|
||||
bool: 是否具有管理员权限
|
||||
"""
|
||||
try:
|
||||
return ctypes.windll.shell32.IsUserAnAdmin() != 0
|
||||
except:
|
||||
return False
|
||||
|
||||
def backup_file(self, source_path: Path, backup_name: Optional[str] = None) -> Optional[Path]:
|
||||
"""备份文件
|
||||
|
||||
Args:
|
||||
source_path: 源文件路径
|
||||
backup_name: 备份文件名(可选)
|
||||
|
||||
Returns:
|
||||
Optional[Path]: 备份文件路径,失败返回None
|
||||
"""
|
||||
try:
|
||||
if not source_path.exists():
|
||||
return None
|
||||
|
||||
self.backup_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if backup_name is None:
|
||||
backup_name = f"{source_path.name}.backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
|
||||
backup_path = self.backup_dir / backup_name
|
||||
shutil.copy2(source_path, backup_path)
|
||||
logging.info(f"已备份文件: {source_path} -> {backup_path}")
|
||||
return backup_path
|
||||
except Exception as e:
|
||||
logging.error(f"备份文件失败 {source_path}: {str(e)}")
|
||||
return None
|
||||
|
||||
def update_machine_guid(self) -> bool:
|
||||
"""更新系统的 MachineGuid
|
||||
|
||||
Returns:
|
||||
bool: 是否成功
|
||||
"""
|
||||
if not self.is_admin():
|
||||
logging.error("需要管理员权限来修改 MachineGuid")
|
||||
return False
|
||||
|
||||
try:
|
||||
# 生成新的 GUID
|
||||
new_guid = str(uuid.uuid4())
|
||||
registry_path = r"SOFTWARE\Microsoft\Cryptography"
|
||||
|
||||
try:
|
||||
# 使用管理员权限打开注册表项
|
||||
key = None
|
||||
try:
|
||||
# 先尝试直接打开读取权限
|
||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
|
||||
winreg.KEY_READ | winreg.KEY_WOW64_64KEY)
|
||||
# 读取原始值并备份
|
||||
# 备份原始值
|
||||
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
|
||||
winreg.KEY_READ | winreg.KEY_WOW64_64KEY) as key:
|
||||
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)
|
||||
# 备份原始 GUID
|
||||
backup_path = self.backup_dir / f"MachineGuid.backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
self.backup_dir.mkdir(parents=True, exist_ok=True)
|
||||
with open(backup_path, 'w', encoding='utf-8') as f:
|
||||
f.write(original_guid)
|
||||
logging.info(f"已备份 MachineGuid: {backup_path}")
|
||||
|
||||
# 设置新的 GUID
|
||||
winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
|
||||
winreg.CloseKey(key)
|
||||
logging.info(f"更新系统 MachineGuid 成功: {new_guid}")
|
||||
# 更新 GUID
|
||||
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
|
||||
winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY) as key:
|
||||
winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
|
||||
|
||||
logging.info(f"已更新系统 MachineGuid: {new_guid}")
|
||||
return True
|
||||
|
||||
except WindowsError as e:
|
||||
logging.error(f"更新系统 MachineGuid 失败: {str(e)}")
|
||||
logging.error(f"注册表操作失败: {str(e)}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"更新 MachineGuid 过程出错: {str(e)}")
|
||||
logging.error(f"更新 MachineGuid 失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def clean_registry(self) -> bool:
|
||||
@@ -107,97 +163,111 @@ class CursorRegistry:
|
||||
return False
|
||||
|
||||
def clean_cursor_files(self) -> bool:
|
||||
"""清理Cursor相关的文件和目录,但保留重要的配置和历史记录"""
|
||||
"""清理Cursor相关的文件和目录,但保留重要的配置和历史记录
|
||||
|
||||
Returns:
|
||||
bool: 是否成功
|
||||
"""
|
||||
try:
|
||||
local_app_data = Path(os.getenv('LOCALAPPDATA'))
|
||||
app_data = Path(os.getenv('APPDATA'))
|
||||
storage_path = Path(os.getenv('APPDATA')) / "Cursor" / "User" / "globalStorage" / "storage.json"
|
||||
global_storage_dir = storage_path.parent
|
||||
|
||||
# 需要备份的文件
|
||||
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,先备份
|
||||
# 备份 storage.json
|
||||
if storage_path.exists():
|
||||
if not self.backup_file(storage_path):
|
||||
return False
|
||||
|
||||
# 备份其他重要文件
|
||||
if global_storage_dir.exists():
|
||||
for item in global_storage_dir.iterdir():
|
||||
if item.name not in ["storage.json", "backups"]:
|
||||
try:
|
||||
backup_item_dir = self.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)
|
||||
elif item.is_dir():
|
||||
shutil.copytree(item, backup_item_dir / item.name)
|
||||
|
||||
logging.info(f"已备份: {item}")
|
||||
except Exception as e:
|
||||
logging.error(f"备份失败 {item}: {str(e)}")
|
||||
|
||||
# 更新 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}")
|
||||
with open(storage_path, "r", encoding="utf-8") as f:
|
||||
storage_data = json.load(f)
|
||||
|
||||
if "telemetry.machineId" in storage_data:
|
||||
new_machine_id = self.get_random_hex(32)
|
||||
storage_data["telemetry.machineId"] = new_machine_id
|
||||
logging.info(f"已更新 machineId: {new_machine_id}")
|
||||
|
||||
# 使用 UTF-8 无 BOM 编码保存
|
||||
with open(storage_path, "w", encoding="utf-8", newline='\n') as f:
|
||||
json.dump(storage_data, f, indent=2)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"清理文件/目录失败: {path}, 错误: {str(e)}")
|
||||
|
||||
# 修复 Cursor 启动配置
|
||||
self.fix_cursor_startup()
|
||||
|
||||
logging.error(f"更新 storage.json 失败: {str(e)}")
|
||||
return False
|
||||
|
||||
# 处理更新程序
|
||||
updater_path = Path(os.getenv('LOCALAPPDATA')) / "cursor-updater"
|
||||
if updater_path.exists():
|
||||
try:
|
||||
if updater_path.is_dir():
|
||||
shutil.rmtree(updater_path)
|
||||
else:
|
||||
updater_path.unlink()
|
||||
except Exception as e:
|
||||
logging.error(f"删除更新程序失败: {str(e)}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"清理文件过程出错: {str(e)}")
|
||||
logging.error(f"清理文件失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def disable_auto_update(self) -> bool:
|
||||
"""禁用自动更新功能
|
||||
|
||||
Returns:
|
||||
bool: 是否成功
|
||||
"""
|
||||
try:
|
||||
updater_path = Path(os.getenv('LOCALAPPDATA')) / "cursor-updater"
|
||||
|
||||
# 删除现有目录/文件
|
||||
if updater_path.exists():
|
||||
if updater_path.is_dir():
|
||||
shutil.rmtree(updater_path)
|
||||
else:
|
||||
updater_path.unlink()
|
||||
|
||||
# 创建空文件
|
||||
updater_path.touch()
|
||||
|
||||
# 设置只读属性
|
||||
import stat
|
||||
updater_path.chmod(stat.S_IREAD)
|
||||
|
||||
# 设置文件权限(仅Windows)
|
||||
if os.name == 'nt':
|
||||
import subprocess
|
||||
subprocess.run(
|
||||
f'icacls "{updater_path}" /inheritance:r /grant:r "{os.getenv("USERNAME")}:(R)"',
|
||||
shell=True,
|
||||
check=True
|
||||
)
|
||||
|
||||
logging.info("已禁用自动更新")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"禁用自动更新失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def fix_cursor_startup(self) -> bool:
|
||||
|
||||
227
utils/cursor_resetter.py
Normal file
227
utils/cursor_resetter.py
Normal file
@@ -0,0 +1,227 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import logging
|
||||
import subprocess
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple, Dict
|
||||
|
||||
class CursorResetter:
|
||||
"""Cursor重置工具类,封装PowerShell脚本的核心功能"""
|
||||
|
||||
def __init__(self):
|
||||
self.appdata = os.getenv('APPDATA')
|
||||
self.localappdata = os.getenv('LOCALAPPDATA')
|
||||
self.storage_file = Path(self.appdata) / "Cursor" / "User" / "globalStorage" / "storage.json"
|
||||
self.backup_dir = Path(self.appdata) / "Cursor" / "User" / "globalStorage" / "backups"
|
||||
self.cursor_path = Path(self.localappdata) / "Programs" / "cursor"
|
||||
self.app_path = self.cursor_path / "resources" / "app"
|
||||
self.package_json = self.app_path / "package.json"
|
||||
|
||||
def get_random_hex(self, length: int) -> str:
|
||||
"""生成安全的随机十六进制字符串"""
|
||||
import secrets
|
||||
return secrets.token_hex(length)
|
||||
|
||||
def new_standard_machine_id(self) -> str:
|
||||
"""生成标准格式的机器ID"""
|
||||
template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
||||
import random
|
||||
|
||||
def replace_char(match):
|
||||
r = random.randint(0, 15)
|
||||
v = r if match == 'x' else (r & 0x3 | 0x8)
|
||||
return hex(v)[2:]
|
||||
|
||||
return ''.join(replace_char(c) for c in template)
|
||||
|
||||
def generate_ids(self) -> Dict[str, str]:
|
||||
"""生成所有需要的ID"""
|
||||
# 生成标准格式的ID
|
||||
mac_machine_id = self.new_standard_machine_id()
|
||||
uuid_str = str(uuid.uuid4())
|
||||
|
||||
# 生成带前缀的machineId
|
||||
prefix = "auth0|user_"
|
||||
prefix_hex = ''.join(hex(b)[2:].zfill(2) for b in prefix.encode())
|
||||
random_part = self.get_random_hex(32)
|
||||
machine_id = f"{prefix_hex}{random_part}"
|
||||
|
||||
# 生成大写的SQM ID
|
||||
sqm_id = "{" + str(uuid.uuid4()).upper() + "}"
|
||||
|
||||
return {
|
||||
"mac_machine_id": mac_machine_id,
|
||||
"uuid": uuid_str,
|
||||
"machine_id": machine_id,
|
||||
"sqm_id": sqm_id
|
||||
}
|
||||
|
||||
def backup_file(self, file_path: Path) -> Optional[Path]:
|
||||
"""备份文件"""
|
||||
try:
|
||||
if not file_path.exists():
|
||||
return None
|
||||
|
||||
self.backup_dir.mkdir(parents=True, exist_ok=True)
|
||||
backup_name = f"{file_path.name}.backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
backup_path = self.backup_dir / backup_name
|
||||
|
||||
import shutil
|
||||
shutil.copy2(file_path, backup_path)
|
||||
logging.info(f"已备份文件: {backup_path}")
|
||||
return backup_path
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"备份文件失败: {str(e)}")
|
||||
return None
|
||||
|
||||
def update_machine_guid(self) -> bool:
|
||||
"""更新系统MachineGuid"""
|
||||
try:
|
||||
import winreg
|
||||
new_guid = str(uuid.uuid4())
|
||||
registry_path = r"SOFTWARE\Microsoft\Cryptography"
|
||||
|
||||
# 备份原始值
|
||||
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
|
||||
winreg.KEY_READ | winreg.KEY_WOW64_64KEY) as key:
|
||||
original_guid = winreg.QueryValueEx(key, "MachineGuid")[0]
|
||||
|
||||
# 备份到文件
|
||||
self.backup_dir.mkdir(parents=True, exist_ok=True)
|
||||
backup_path = self.backup_dir / f"MachineGuid.backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
with open(backup_path, 'w', encoding='utf-8') as f:
|
||||
f.write(original_guid)
|
||||
|
||||
# 更新GUID
|
||||
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path, 0,
|
||||
winreg.KEY_WRITE | winreg.KEY_WOW64_64KEY) as key:
|
||||
winreg.SetValueEx(key, "MachineGuid", 0, winreg.REG_SZ, new_guid)
|
||||
|
||||
logging.info(f"已更新系统MachineGuid: {new_guid}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"更新MachineGuid失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def update_storage_json(self) -> bool:
|
||||
"""更新storage.json文件"""
|
||||
try:
|
||||
if not self.storage_file.exists():
|
||||
logging.error(f"未找到配置文件: {self.storage_file}")
|
||||
return False
|
||||
|
||||
# 备份文件
|
||||
if not self.backup_file(self.storage_file):
|
||||
logging.warning("配置文件备份失败")
|
||||
|
||||
# 生成新ID
|
||||
ids = self.generate_ids()
|
||||
|
||||
# 读取并更新配置
|
||||
with open(self.storage_file, "r", encoding="utf-8") as f:
|
||||
config = json.load(f)
|
||||
|
||||
# 更新ID
|
||||
config['telemetry.machineId'] = ids['machine_id']
|
||||
config['telemetry.macMachineId'] = ids['mac_machine_id']
|
||||
config['telemetry.devDeviceId'] = ids['uuid']
|
||||
config['telemetry.sqmId'] = ids['sqm_id']
|
||||
|
||||
# 保存更新
|
||||
with open(self.storage_file, "w", encoding="utf-8", newline='\n') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
|
||||
logging.info("已更新配置文件")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"更新配置文件失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def disable_auto_update(self) -> bool:
|
||||
"""禁用自动更新"""
|
||||
try:
|
||||
updater_path = Path(self.localappdata) / "cursor-updater"
|
||||
|
||||
# 删除现有文件/目录
|
||||
if updater_path.exists():
|
||||
if updater_path.is_dir():
|
||||
import shutil
|
||||
shutil.rmtree(updater_path)
|
||||
else:
|
||||
updater_path.unlink()
|
||||
|
||||
# 创建空文件并设置只读
|
||||
updater_path.touch()
|
||||
import stat
|
||||
updater_path.chmod(stat.S_IREAD)
|
||||
|
||||
# 设置文件权限
|
||||
if os.name == 'nt':
|
||||
subprocess.run(
|
||||
f'icacls "{updater_path}" /inheritance:r /grant:r "{os.getenv("USERNAME")}:(R)"',
|
||||
shell=True,
|
||||
check=True
|
||||
)
|
||||
|
||||
logging.info("已禁用自动更新")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"禁用自动更新失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def reset_cursor(self, disable_update: bool = True) -> Tuple[bool, str]:
|
||||
"""重置Cursor
|
||||
|
||||
Args:
|
||||
disable_update: 是否禁用自动更新
|
||||
|
||||
Returns:
|
||||
Tuple[bool, str]: (是否成功, 消息)
|
||||
"""
|
||||
try:
|
||||
# 1. 检查管理员权限
|
||||
if os.name == 'nt':
|
||||
import ctypes
|
||||
if not ctypes.windll.shell32.IsUserAnAdmin():
|
||||
return False, "需要管理员权限来执行重置操作"
|
||||
|
||||
# 2. 更新配置文件
|
||||
if not self.update_storage_json():
|
||||
return False, "更新配置文件失败"
|
||||
|
||||
# 3. 更新系统MachineGuid
|
||||
if not self.update_machine_guid():
|
||||
return False, "更新系统MachineGuid失败"
|
||||
|
||||
# 4. 禁用自动更新(如果需要)
|
||||
if disable_update and not self.disable_auto_update():
|
||||
logging.warning("禁用自动更新失败")
|
||||
|
||||
# 5. 修改package.json
|
||||
if self.package_json.exists():
|
||||
try:
|
||||
with open(self.package_json, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if "machineId" in data:
|
||||
del data["machineId"]
|
||||
data["updateUrl"] = ""
|
||||
data["disableUpdate"] = True
|
||||
|
||||
with open(self.package_json, "w", encoding="utf-8", newline='\n') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
except Exception as e:
|
||||
logging.warning(f"修改package.json失败: {str(e)}")
|
||||
|
||||
return True, "Cursor重置成功"
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"重置过程出错: {str(e)}")
|
||||
return False, f"重置失败: {str(e)}"
|
||||
Reference in New Issue
Block a user