Compare commits
3 Commits
039cd06e43
...
c2e3c99b8a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2e3c99b8a | ||
|
|
716b2dc47b | ||
|
|
0435e586ab |
@@ -257,25 +257,118 @@ class AccountSwitcher:
|
||||
def reset_machine_id(self) -> bool:
|
||||
"""重置机器码"""
|
||||
try:
|
||||
# 读取package.json
|
||||
with open(self.package_json, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
# 1. 先关闭所有Cursor进程
|
||||
if sys.platform == "win32":
|
||||
os.system("taskkill /f /im Cursor.exe >nul 2>&1")
|
||||
time.sleep(2)
|
||||
|
||||
# 删除machineId
|
||||
if "machineId" in data:
|
||||
del data["machineId"]
|
||||
|
||||
# 保存文件
|
||||
with open(self.package_json, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
# 2. 删除 package.json 中的 machineId
|
||||
if self.package_json.exists():
|
||||
with open(self.package_json, "r", encoding="utf-8") as f:
|
||||
data = json.load(f)
|
||||
|
||||
if "machineId" in data:
|
||||
del data["machineId"]
|
||||
|
||||
with open(self.package_json, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
# 3. 清理特定的配置文件和缓存
|
||||
local_app_data = Path(os.getenv('LOCALAPPDATA'))
|
||||
cursor_path = local_app_data / "Cursor"
|
||||
|
||||
# 需要清理的目录
|
||||
cache_dirs = [
|
||||
cursor_path / "Cache",
|
||||
cursor_path / "Code Cache",
|
||||
cursor_path / "GPUCache",
|
||||
cursor_path / "Local Storage" / "leveldb"
|
||||
]
|
||||
|
||||
# 需要删除的配置文件
|
||||
config_files = [
|
||||
cursor_path / "User" / "globalStorage" / "storage.json",
|
||||
cursor_path / "User" / "globalStorage" / "state.json",
|
||||
self.app_path / "config.json",
|
||||
self.app_path / "state.json",
|
||||
self.app_path / "settings.json"
|
||||
]
|
||||
|
||||
# 清理缓存目录
|
||||
for dir_path in cache_dirs:
|
||||
if dir_path.exists():
|
||||
try:
|
||||
import shutil
|
||||
shutil.rmtree(str(dir_path))
|
||||
logging.info(f"清理目录成功: {dir_path}")
|
||||
except Exception as e:
|
||||
logging.warning(f"清理目录失败: {dir_path}, 错误: {str(e)}")
|
||||
|
||||
# 删除配置文件
|
||||
for file_path in config_files:
|
||||
if file_path.exists():
|
||||
try:
|
||||
os.remove(file_path)
|
||||
logging.info(f"删除配置文件成功: {file_path}")
|
||||
except Exception as e:
|
||||
logging.warning(f"删除配置文件失败: {file_path}, 错误: {str(e)}")
|
||||
|
||||
# 4. 刷新注册表
|
||||
if not self.registry.refresh_registry():
|
||||
logging.warning("注册表刷新失败")
|
||||
|
||||
# 5. 删除卸载注册表项
|
||||
try:
|
||||
import winreg
|
||||
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Uninstall", 0, winreg.KEY_ALL_ACCESS) as key:
|
||||
# 遍历所有子键,找到Cursor相关的
|
||||
i = 0
|
||||
while True:
|
||||
try:
|
||||
subkey_name = winreg.EnumKey(key, i)
|
||||
if "Cursor" in subkey_name:
|
||||
winreg.DeleteKey(key, subkey_name)
|
||||
logging.info(f"删除注册表项成功: {subkey_name}")
|
||||
i += 1
|
||||
except WindowsError:
|
||||
break
|
||||
except Exception as e:
|
||||
logging.warning(f"删除注册表项失败: {str(e)}")
|
||||
|
||||
# 6. 重启Cursor
|
||||
cursor_exe = self.cursor_path / "Cursor.exe"
|
||||
if cursor_exe.exists():
|
||||
os.startfile(str(cursor_exe))
|
||||
logging.info("Cursor重启成功")
|
||||
|
||||
logging.info("机器码重置完成")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"重置机器码失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def bypass_version_limit(self) -> Tuple[bool, str]:
|
||||
"""突破Cursor版本限制"""
|
||||
try:
|
||||
# 1. 先关闭所有Cursor进程
|
||||
if sys.platform == "win32":
|
||||
os.system("taskkill /f /im Cursor.exe >nul 2>&1")
|
||||
time.sleep(2)
|
||||
|
||||
# 2. 重置机器码
|
||||
if not self.reset_machine_id():
|
||||
return False, "重置机器码失败"
|
||||
|
||||
# 3. 等待Cursor启动
|
||||
time.sleep(3)
|
||||
|
||||
return True, "突破版本限制成功,Cursor已重启"
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"突破版本限制失败: {str(e)}")
|
||||
return False, f"突破失败: {str(e)}"
|
||||
|
||||
def activate_and_switch(self, activation_code: str) -> Tuple[bool, str]:
|
||||
"""激活并切换账号
|
||||
|
||||
@@ -515,6 +608,49 @@ class AccountSwitcher:
|
||||
logging.error(f"刷新授权过程出错: {str(e)}")
|
||||
return False, f"刷新失败: {str(e)}"
|
||||
|
||||
def disable_cursor_update(self) -> Tuple[bool, str]:
|
||||
"""禁用Cursor更新"""
|
||||
try:
|
||||
# 1. 先关闭所有Cursor进程
|
||||
if sys.platform == "win32":
|
||||
os.system("taskkill /f /im Cursor.exe >nul 2>&1")
|
||||
time.sleep(2)
|
||||
|
||||
# 2. 删除updater目录并创建同名文件以阻止更新
|
||||
updater_path = Path(os.getenv('LOCALAPPDATA')) / "cursor-updater"
|
||||
|
||||
try:
|
||||
# 如果是目录,则删除
|
||||
if updater_path.is_dir():
|
||||
import shutil
|
||||
shutil.rmtree(str(updater_path))
|
||||
logging.info("删除updater目录成功")
|
||||
|
||||
# 如果是文件,则删除
|
||||
if updater_path.is_file():
|
||||
os.remove(str(updater_path))
|
||||
logging.info("删除updater文件成功")
|
||||
|
||||
# 创建同名空文件
|
||||
updater_path.touch()
|
||||
logging.info("创建updater空文件成功")
|
||||
|
||||
# 3. 重启Cursor
|
||||
cursor_exe = self.cursor_path / "Cursor.exe"
|
||||
if cursor_exe.exists():
|
||||
os.startfile(str(cursor_exe))
|
||||
logging.info("Cursor重启成功")
|
||||
|
||||
return True, "Cursor更新已禁用,程序已重启"
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"操作updater文件失败: {str(e)}")
|
||||
return False, f"禁用更新失败: {str(e)}"
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"禁用Cursor更新失败: {str(e)}")
|
||||
return False, f"禁用更新失败: {str(e)}"
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
try:
|
||||
|
||||
@@ -5,6 +5,7 @@ from pathlib import Path
|
||||
import logging
|
||||
import os
|
||||
from PIL import Image, ImageTk
|
||||
import time
|
||||
sys.path.append(str(Path(__file__).parent.parent))
|
||||
|
||||
from utils.config import Config
|
||||
@@ -123,7 +124,7 @@ class MainWindow:
|
||||
self.style.configure("Action.TButton", padding=8)
|
||||
ttk.Button(btn_frame, text="刷新Cursor编辑器授权", command=self.reset_machine_id, style="Action.TButton").pack(fill="x", pady=2)
|
||||
ttk.Button(btn_frame, text="突破Cursor0.45.x限制", command=self.dummy_function, style="Action.TButton").pack(fill="x", pady=2)
|
||||
ttk.Button(btn_frame, text="禁用Cursor版本更新", command=self.dummy_function, style="Action.TButton").pack(fill="x", pady=2)
|
||||
ttk.Button(btn_frame, text="禁用Cursor版本更新", command=self.disable_cursor_update, style="Action.TButton").pack(fill="x", pady=2)
|
||||
|
||||
def copy_device_id(self):
|
||||
"""复制设备ID到剪贴板"""
|
||||
@@ -222,10 +223,7 @@ class MainWindow:
|
||||
self.status_text.config(state="disabled")
|
||||
|
||||
def check_status(self):
|
||||
"""检查会员状态
|
||||
Returns:
|
||||
bool: True 表示激活状态正常,False 表示未激活或已过期
|
||||
"""
|
||||
"""检查会员状态"""
|
||||
try:
|
||||
self.status_var.set("正在检查状态...")
|
||||
self.root.update()
|
||||
@@ -234,7 +232,6 @@ class MainWindow:
|
||||
if status:
|
||||
self.update_status_display(status)
|
||||
if status.get('status') == 'inactive':
|
||||
messagebox.showwarning("警告", "当前设备未激活或激活已失效")
|
||||
self.status_var.set("未激活")
|
||||
return False
|
||||
self.status_var.set("状态检查完成")
|
||||
@@ -244,23 +241,74 @@ class MainWindow:
|
||||
inactive_status = {
|
||||
"hardware_id": self.switcher.hardware_id,
|
||||
"expire_time": "",
|
||||
"days": 0,
|
||||
"days_left": 0,
|
||||
"total_days": 0,
|
||||
"status": "inactive",
|
||||
"last_activation": {}
|
||||
"activation_records": []
|
||||
}
|
||||
self.update_status_display(inactive_status)
|
||||
self.status_var.set("未激活")
|
||||
messagebox.showwarning("警告", "当前设备未激活")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"检查状态失败: {str(e)}")
|
||||
self.status_var.set("状态检查失败")
|
||||
# 显示错误消息
|
||||
messagebox.showerror("错误", f"检查状态失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def show_purchase_info(self):
|
||||
"""显示购买信息"""
|
||||
# 创建自定义对话框
|
||||
dialog = tk.Toplevel(self.root)
|
||||
dialog.title("提示")
|
||||
dialog.geometry("400x280") # 增加高度
|
||||
dialog.resizable(False, False)
|
||||
|
||||
# 设置模态
|
||||
dialog.transient(self.root)
|
||||
dialog.grab_set()
|
||||
|
||||
# 创建提示图标
|
||||
icon_frame = ttk.Frame(dialog)
|
||||
icon_frame.pack(pady=10)
|
||||
ttk.Label(icon_frame, text="ℹ️", font=("Segoe UI", 24)).pack()
|
||||
|
||||
# 创建消息文本
|
||||
message_frame = ttk.Frame(dialog)
|
||||
message_frame.pack(pady=5, padx=20)
|
||||
ttk.Label(message_frame, text="您还不是会员,请先购买激活会员用讯。", font=("Microsoft YaHei UI", 10)).pack()
|
||||
|
||||
# 创建可复制的文本框
|
||||
buy_info = "闲鱼:xxxx\n微信:behikcigar\n网站自助购买:nezhacursor.nosqli.com"
|
||||
text = tk.Text(dialog, height=4, width=40, font=("Microsoft YaHei UI", 9))
|
||||
text.pack(pady=5, padx=20)
|
||||
text.insert("1.0", buy_info)
|
||||
text.config(state="normal") # 允许选择和复制
|
||||
|
||||
# 创建按钮框架
|
||||
btn_frame = ttk.Frame(dialog)
|
||||
btn_frame.pack(pady=10)
|
||||
|
||||
# 复制按钮
|
||||
def copy_info():
|
||||
dialog.clipboard_clear()
|
||||
dialog.clipboard_append(buy_info)
|
||||
messagebox.showinfo("提示", "购买信息已复制到剪贴板", parent=dialog)
|
||||
|
||||
ttk.Button(btn_frame, text="复制信息", command=copy_info).pack(side="left", padx=5)
|
||||
ttk.Button(btn_frame, text="确定", command=dialog.destroy).pack(side="left", padx=5)
|
||||
|
||||
# 设置对话框位置为居中
|
||||
dialog.update_idletasks()
|
||||
width = dialog.winfo_width()
|
||||
height = dialog.winfo_height()
|
||||
x = (dialog.winfo_screenwidth() // 2) - (width // 2)
|
||||
y = (dialog.winfo_screenheight() // 2) - (height // 2)
|
||||
dialog.geometry(f"{width}x{height}+{x}+{y}")
|
||||
|
||||
# 等待对话框关闭
|
||||
self.root.wait_window(dialog)
|
||||
|
||||
def minimize_window(self):
|
||||
"""最小化窗口"""
|
||||
self.root.iconify()
|
||||
@@ -276,31 +324,71 @@ class MainWindow:
|
||||
"""窗口关闭处理"""
|
||||
try:
|
||||
logging.info("正在关闭程序...")
|
||||
# 先退出主循环
|
||||
self.root.quit()
|
||||
# 等待一小段时间确保资源释放
|
||||
time.sleep(0.5)
|
||||
except Exception as e:
|
||||
logging.error(f"关闭程序时出错: {str(e)}")
|
||||
finally:
|
||||
self.root.destroy()
|
||||
try:
|
||||
# 销毁窗口
|
||||
self.root.destroy()
|
||||
# 再等待一小段时间
|
||||
time.sleep(0.5)
|
||||
# 强制结束进程
|
||||
if sys.platform == "win32":
|
||||
import os
|
||||
os._exit(0)
|
||||
except:
|
||||
# 如果还是无法正常关闭,直接强制退出
|
||||
os._exit(0)
|
||||
|
||||
def run(self):
|
||||
"""运行程序"""
|
||||
self.root.mainloop()
|
||||
|
||||
def dummy_function(self):
|
||||
"""占位函数"""
|
||||
# 先检查状态
|
||||
if not self.check_status():
|
||||
return
|
||||
messagebox.showinfo("提示", "此功能暂未实现")
|
||||
|
||||
def reset_machine_id(self):
|
||||
"""刷新Cursor编辑器授权"""
|
||||
if not self.check_status():
|
||||
self.show_purchase_info()
|
||||
return
|
||||
|
||||
try:
|
||||
# 刷新授权
|
||||
success, message = self.switcher.refresh_cursor_auth()
|
||||
if success:
|
||||
messagebox.showinfo("成功", "Cursor编辑器授权刷新成功!\n" + message)
|
||||
else:
|
||||
messagebox.showerror("错误", message)
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"刷新失败: {str(e)}")
|
||||
messagebox.showerror("错误", f"刷新失败: {str(e)}")
|
||||
|
||||
def disable_cursor_update(self):
|
||||
"""禁用Cursor版本更新"""
|
||||
if not self.check_status():
|
||||
self.show_purchase_info()
|
||||
return
|
||||
|
||||
try:
|
||||
success, message = self.switcher.disable_cursor_update()
|
||||
if success:
|
||||
messagebox.showinfo("成功", message)
|
||||
else:
|
||||
messagebox.showerror("错误", message)
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"操作失败: {str(e)}")
|
||||
|
||||
def dummy_function(self):
|
||||
"""突破版本限制"""
|
||||
if not self.check_status():
|
||||
self.show_purchase_info()
|
||||
return
|
||||
|
||||
try:
|
||||
success, message = self.switcher.bypass_version_limit()
|
||||
if success:
|
||||
messagebox.showinfo("成功", message)
|
||||
else:
|
||||
messagebox.showerror("错误", message)
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"操作失败: {str(e)}")
|
||||
@@ -2,6 +2,7 @@ import os
|
||||
import winreg
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import uuid
|
||||
|
||||
class CursorRegistry:
|
||||
"""Cursor注册表操作工具类"""
|
||||
@@ -9,14 +10,27 @@ 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:
|
||||
"""刷新Cursor相关的注册表项
|
||||
|
||||
"""刷新注册表
|
||||
Returns:
|
||||
bool: 是否成功
|
||||
"""
|
||||
try:
|
||||
# 生成新的GUID
|
||||
new_guid = str(uuid.uuid4())
|
||||
|
||||
# 修改 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():
|
||||
@@ -42,7 +56,7 @@ class CursorRegistry:
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"刷新注册表过程出错: {str(e)}")
|
||||
logging.error(f"刷新注册表失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def clean_registry(self) -> bool:
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.0.2
|
||||
3.0.9
|
||||
Reference in New Issue
Block a user