添加项目核心文件和 .gitignore
This commit is contained in:
@@ -5,23 +5,34 @@ import logging
|
|||||||
import subprocess
|
import subprocess
|
||||||
import uuid
|
import uuid
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
from typing import Optional, Dict, Tuple
|
from typing import Optional, Dict, Tuple
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from utils.config import Config
|
from utils.config import Config
|
||||||
|
from utils.cursor_registry import CursorRegistry
|
||||||
|
from cursor_auth_manager import CursorAuthManager
|
||||||
|
|
||||||
def get_hardware_id() -> str:
|
def get_hardware_id() -> str:
|
||||||
"""获取硬件唯一标识"""
|
"""获取硬件唯一标识"""
|
||||||
try:
|
try:
|
||||||
|
# 创建startupinfo对象来隐藏命令行窗口
|
||||||
|
startupinfo = None
|
||||||
|
if sys.platform == "win32":
|
||||||
|
startupinfo = subprocess.STARTUPINFO()
|
||||||
|
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||||
|
startupinfo.wShowWindow = subprocess.SW_HIDE
|
||||||
|
|
||||||
# 获取CPU信息
|
# 获取CPU信息
|
||||||
cpu_info = subprocess.check_output('wmic cpu get ProcessorId').decode()
|
cpu_info = subprocess.check_output('wmic cpu get ProcessorId', startupinfo=startupinfo).decode()
|
||||||
cpu_id = cpu_info.split('\n')[1].strip()
|
cpu_id = cpu_info.split('\n')[1].strip()
|
||||||
|
|
||||||
# 获取主板序列号
|
# 获取主板序列号
|
||||||
board_info = subprocess.check_output('wmic baseboard get SerialNumber').decode()
|
board_info = subprocess.check_output('wmic baseboard get SerialNumber', startupinfo=startupinfo).decode()
|
||||||
board_id = board_info.split('\n')[1].strip()
|
board_id = board_info.split('\n')[1].strip()
|
||||||
|
|
||||||
# 获取BIOS序列号
|
# 获取BIOS序列号
|
||||||
bios_info = subprocess.check_output('wmic bios get SerialNumber').decode()
|
bios_info = subprocess.check_output('wmic bios get SerialNumber', startupinfo=startupinfo).decode()
|
||||||
bios_id = bios_info.split('\n')[1].strip()
|
bios_id = bios_info.split('\n')[1].strip()
|
||||||
|
|
||||||
# 组合信息并生成哈希
|
# 组合信息并生成哈希
|
||||||
@@ -32,35 +43,6 @@ def get_hardware_id() -> str:
|
|||||||
# 如果获取失败,使用UUID作为备选方案
|
# 如果获取失败,使用UUID作为备选方案
|
||||||
return str(uuid.uuid4())
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
class CursorAuthManager:
|
|
||||||
def __init__(self):
|
|
||||||
self.cursor_path = Path(os.path.expanduser("~")) / "AppData" / "Local" / "Programs" / "Cursor"
|
|
||||||
self.app_path = self.cursor_path / "resources" / "app"
|
|
||||||
self.package_json = self.app_path / "package.json"
|
|
||||||
|
|
||||||
def update_auth(self, email: str, access_token: str, refresh_token: str) -> bool:
|
|
||||||
"""更新Cursor认证信息"""
|
|
||||||
try:
|
|
||||||
# 读取package.json
|
|
||||||
with open(self.package_json, "r", encoding="utf-8") as f:
|
|
||||||
data = json.load(f)
|
|
||||||
|
|
||||||
# 更新认证信息
|
|
||||||
data["email"] = email
|
|
||||||
data["accessToken"] = access_token
|
|
||||||
data["refreshToken"] = refresh_token
|
|
||||||
|
|
||||||
# 保存更新后的文件
|
|
||||||
with open(self.package_json, "w", encoding="utf-8") as f:
|
|
||||||
json.dump(data, f, indent=2)
|
|
||||||
|
|
||||||
logging.info(f"认证信息更新成功: {email}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logging.error(f"更新认证信息失败: {str(e)}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
class AccountSwitcher:
|
class AccountSwitcher:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.cursor_path = Path(os.path.expanduser("~")) / "AppData" / "Local" / "Programs" / "Cursor"
|
self.cursor_path = Path(os.path.expanduser("~")) / "AppData" / "Local" / "Programs" / "Cursor"
|
||||||
@@ -69,6 +51,7 @@ class AccountSwitcher:
|
|||||||
self.auth_manager = CursorAuthManager()
|
self.auth_manager = CursorAuthManager()
|
||||||
self.config = Config()
|
self.config = Config()
|
||||||
self.hardware_id = get_hardware_id()
|
self.hardware_id = get_hardware_id()
|
||||||
|
self.registry = CursorRegistry() # 添加注册表操作工具类
|
||||||
|
|
||||||
def get_device_info(self) -> dict:
|
def get_device_info(self) -> dict:
|
||||||
"""获取设备信息"""
|
"""获取设备信息"""
|
||||||
@@ -384,6 +367,142 @@ class AccountSwitcher:
|
|||||||
"activation_records": []
|
"activation_records": []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def restart_cursor(self) -> bool:
|
||||||
|
"""重启Cursor编辑器
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功重启
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logging.info("正在重启Cursor...")
|
||||||
|
if sys.platform == "win32":
|
||||||
|
# Windows系统
|
||||||
|
# 关闭Cursor
|
||||||
|
os.system("taskkill /f /im Cursor.exe 2>nul")
|
||||||
|
time.sleep(2)
|
||||||
|
# 获取Cursor安装路径
|
||||||
|
cursor_exe = self.cursor_path / "Cursor.exe"
|
||||||
|
if cursor_exe.exists():
|
||||||
|
# 启动Cursor
|
||||||
|
os.startfile(str(cursor_exe))
|
||||||
|
logging.info("Cursor重启成功")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logging.error(f"未找到Cursor程序: {cursor_exe}")
|
||||||
|
return False
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
# macOS系统
|
||||||
|
os.system("killall Cursor 2>/dev/null")
|
||||||
|
time.sleep(2)
|
||||||
|
os.system("open -a Cursor")
|
||||||
|
logging.info("Cursor重启成功")
|
||||||
|
return True
|
||||||
|
elif sys.platform == "linux":
|
||||||
|
# Linux系统
|
||||||
|
os.system("pkill -f cursor")
|
||||||
|
time.sleep(2)
|
||||||
|
os.system("cursor &")
|
||||||
|
logging.info("Cursor重启成功")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logging.error(f"不支持的操作系统: {sys.platform}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"重启Cursor时发生错误: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def refresh_cursor_auth(self) -> Tuple[bool, str]:
|
||||||
|
"""刷新Cursor授权
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple[bool, str]: (是否成功, 提示消息)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 获取未使用的账号
|
||||||
|
endpoint = "https://cursorapi.nosqli.com/admin/api.account/getUnused"
|
||||||
|
data = {
|
||||||
|
"machine_id": self.hardware_id
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 添加SSL验证选项和超时设置
|
||||||
|
response = requests.post(
|
||||||
|
endpoint,
|
||||||
|
json=data,
|
||||||
|
headers=headers,
|
||||||
|
timeout=30, # 增加超时时间
|
||||||
|
verify=False, # 禁用SSL验证
|
||||||
|
)
|
||||||
|
# 禁用SSL警告
|
||||||
|
requests.packages.urllib3.disable_warnings()
|
||||||
|
|
||||||
|
response_data = response.json()
|
||||||
|
|
||||||
|
if response_data.get("code") == 200:
|
||||||
|
account_data = response_data.get("data", {})
|
||||||
|
|
||||||
|
# 获取账号信息
|
||||||
|
email = account_data.get("email", "")
|
||||||
|
access_token = account_data.get("access_token", "")
|
||||||
|
refresh_token = account_data.get("refresh_token", "")
|
||||||
|
expire_time = account_data.get("expire_time", "")
|
||||||
|
days_left = account_data.get("days_left", 0)
|
||||||
|
|
||||||
|
if not all([email, access_token, refresh_token]):
|
||||||
|
return False, "获取账号信息不完整"
|
||||||
|
|
||||||
|
# 更新Cursor认证信息
|
||||||
|
if not self.auth_manager.update_auth(email, access_token, refresh_token):
|
||||||
|
return False, "更新Cursor认证信息失败"
|
||||||
|
|
||||||
|
# 重置机器码
|
||||||
|
if not self.reset_machine_id():
|
||||||
|
return False, "重置机器码失败"
|
||||||
|
|
||||||
|
# 刷新注册表
|
||||||
|
if not self.registry.refresh_registry():
|
||||||
|
logging.warning("注册表刷新失败,但不影响主要功能")
|
||||||
|
|
||||||
|
# 重启Cursor
|
||||||
|
if not self.auth_manager.restart_cursor():
|
||||||
|
return False, "重启Cursor失败"
|
||||||
|
# 重启Cursor
|
||||||
|
# if not self.restart_cursor():
|
||||||
|
# logging.warning("Cursor重启失败,请手动重启")
|
||||||
|
# return True, f"授权刷新成功,请手动重启Cursor编辑器\n邮箱: {email}\n到期时间: {expire_time}\n剩余天数: {days_left}天"
|
||||||
|
|
||||||
|
return True, f"授权刷新成功,Cursor编辑器已重启\n邮箱: {email}\n"
|
||||||
|
|
||||||
|
elif response_data.get("code") == 404:
|
||||||
|
return False, "没有可用的未使用账号"
|
||||||
|
else:
|
||||||
|
error_msg = response_data.get("msg", "未知错误")
|
||||||
|
logging.error(f"获取未使用账号失败: {error_msg}")
|
||||||
|
return False, f"获取账号失败: {error_msg}"
|
||||||
|
|
||||||
|
except requests.exceptions.SSLError as e:
|
||||||
|
logging.error(f"SSL验证失败: {str(e)}")
|
||||||
|
return False, "SSL验证失败,请检查网络设置"
|
||||||
|
except requests.exceptions.ConnectionError as e:
|
||||||
|
logging.error(f"网络连接错误: {str(e)}")
|
||||||
|
return False, "网络连接失败,请检查网络设置"
|
||||||
|
except requests.exceptions.Timeout as e:
|
||||||
|
logging.error(f"请求超时: {str(e)}")
|
||||||
|
return False, "请求超时,请稍后重试"
|
||||||
|
except requests.RequestException as e:
|
||||||
|
logging.error(f"请求失败: {str(e)}")
|
||||||
|
return False, f"网络请求失败: {str(e)}"
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"未知错误: {str(e)}")
|
||||||
|
return False, f"发生未知错误: {str(e)}"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"刷新授权过程出错: {str(e)}")
|
||||||
|
return False, f"刷新失败: {str(e)}"
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""主函数"""
|
"""主函数"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
134
cursor_auth_manager.py
Normal file
134
cursor_auth_manager.py
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
class CursorAuthManager:
|
||||||
|
"""Cursor认证信息管理器"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# 判断操作系统
|
||||||
|
if sys.platform == "win32": # Windows
|
||||||
|
appdata = os.getenv("APPDATA")
|
||||||
|
if appdata is None:
|
||||||
|
raise EnvironmentError("APPDATA 环境变量未设置")
|
||||||
|
self.db_path = os.path.join(
|
||||||
|
appdata, "Cursor", "User", "globalStorage", "state.vscdb"
|
||||||
|
)
|
||||||
|
elif sys.platform == "darwin": # macOS
|
||||||
|
self.db_path = os.path.abspath(os.path.expanduser(
|
||||||
|
"~/Library/Application Support/Cursor/User/globalStorage/state.vscdb"
|
||||||
|
))
|
||||||
|
elif sys.platform == "linux" : # Linux 和其他类Unix系统
|
||||||
|
self.db_path = os.path.abspath(os.path.expanduser(
|
||||||
|
"~/.config/Cursor/User/globalStorage/state.vscdb"
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
raise NotImplementedError(f"不支持的操作系统: {sys.platform}")
|
||||||
|
|
||||||
|
self.cursor_path = Path(os.path.expanduser("~")) / "AppData" / "Local" / "Programs" / "Cursor"
|
||||||
|
|
||||||
|
def update_auth(self, email=None, access_token=None, refresh_token=None):
|
||||||
|
"""
|
||||||
|
更新Cursor的认证信息
|
||||||
|
:param email: 新的邮箱地址
|
||||||
|
:param access_token: 新的访问令牌
|
||||||
|
:param refresh_token: 新的刷新令牌
|
||||||
|
:return: bool 是否成功更新
|
||||||
|
"""
|
||||||
|
updates = []
|
||||||
|
# 登录状态
|
||||||
|
updates.append(("cursorAuth/cachedSignUpType", "Auth_0"))
|
||||||
|
|
||||||
|
if email is not None:
|
||||||
|
updates.append(("cursorAuth/cachedEmail", email))
|
||||||
|
if access_token is not None:
|
||||||
|
updates.append(("cursorAuth/accessToken", access_token))
|
||||||
|
if refresh_token is not None:
|
||||||
|
updates.append(("cursorAuth/refreshToken", refresh_token))
|
||||||
|
|
||||||
|
if not updates:
|
||||||
|
logging.warning("没有提供任何要更新的值")
|
||||||
|
return False
|
||||||
|
|
||||||
|
conn = None
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect(self.db_path)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
for key, value in updates:
|
||||||
|
# 检查key是否存在
|
||||||
|
check_query = f"SELECT COUNT(*) FROM itemTable WHERE key = ?"
|
||||||
|
cursor.execute(check_query, (key,))
|
||||||
|
if cursor.fetchone()[0] == 0:
|
||||||
|
insert_query = "INSERT INTO itemTable (key, value) VALUES (?, ?)"
|
||||||
|
cursor.execute(insert_query, (key, value))
|
||||||
|
else:
|
||||||
|
update_query = "UPDATE itemTable SET value = ? WHERE key = ?"
|
||||||
|
cursor.execute(update_query, (value, key))
|
||||||
|
|
||||||
|
if cursor.rowcount > 0:
|
||||||
|
logging.info(f"成功更新 {key.split('/')[-1]}")
|
||||||
|
else:
|
||||||
|
logging.warning(f"未找到 {key.split('/')[-1]} 或值未变化")
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
logging.info(f"认证信息更新成功: {email}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except sqlite3.Error as e:
|
||||||
|
logging.error(f"数据库错误: {str(e)}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"更新认证信息失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if conn:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def restart_cursor(self) -> bool:
|
||||||
|
"""重启Cursor编辑器
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功重启
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logging.info("正在重启Cursor...")
|
||||||
|
if sys.platform == "win32":
|
||||||
|
# Windows系统
|
||||||
|
# 关闭Cursor
|
||||||
|
os.system("taskkill /f /im Cursor.exe 2>nul")
|
||||||
|
time.sleep(2)
|
||||||
|
# 获取Cursor安装路径
|
||||||
|
cursor_exe = self.cursor_path / "Cursor.exe"
|
||||||
|
if cursor_exe.exists():
|
||||||
|
# 启动Cursor
|
||||||
|
os.startfile(str(cursor_exe))
|
||||||
|
logging.info("Cursor重启成功")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logging.error(f"未找到Cursor程序: {cursor_exe}")
|
||||||
|
return False
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
# macOS系统
|
||||||
|
os.system("killall Cursor 2>/dev/null")
|
||||||
|
time.sleep(2)
|
||||||
|
os.system("open -a Cursor")
|
||||||
|
logging.info("Cursor重启成功")
|
||||||
|
return True
|
||||||
|
elif sys.platform == "linux":
|
||||||
|
# Linux系统
|
||||||
|
os.system("pkill -f cursor")
|
||||||
|
time.sleep(2)
|
||||||
|
os.system("cursor &")
|
||||||
|
logging.info("Cursor重启成功")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
logging.error(f"不支持的操作系统: {sys.platform}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"重启Cursor时发生错误: {str(e)}")
|
||||||
|
return False
|
||||||
@@ -110,8 +110,8 @@ class MainWindow:
|
|||||||
btn_frame.pack(fill="x", pady=5)
|
btn_frame.pack(fill="x", pady=5)
|
||||||
|
|
||||||
self.style.configure("Action.TButton", padding=8)
|
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="刷新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="突破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.dummy_function, style="Action.TButton").pack(fill="x", pady=2)
|
||||||
|
|
||||||
def copy_device_id(self):
|
def copy_device_id(self):
|
||||||
@@ -283,21 +283,13 @@ class MainWindow:
|
|||||||
messagebox.showinfo("提示", "此功能暂未实现")
|
messagebox.showinfo("提示", "此功能暂未实现")
|
||||||
|
|
||||||
def reset_machine_id(self):
|
def reset_machine_id(self):
|
||||||
"""重置机器码"""
|
"""刷新Cursor编辑器授权"""
|
||||||
# 先检查状态
|
|
||||||
if not self.check_status():
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.switcher.reset_machine_id():
|
# 刷新授权
|
||||||
messagebox.showinfo("成功", "机器码重置成功")
|
success, message = self.switcher.refresh_cursor_auth()
|
||||||
# 重置后检查一次状态
|
if success:
|
||||||
self.check_status()
|
messagebox.showinfo("成功", "Cursor编辑器授权刷新成功!\n" + message)
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("错误", "机器码重置失败,请查看日志")
|
messagebox.showerror("错误", message)
|
||||||
# 失败后也检查状态
|
|
||||||
self.check_status()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("错误", f"重置失败: {str(e)}")
|
messagebox.showerror("错误", f"刷新失败: {str(e)}")
|
||||||
# 出错后也检查状态
|
|
||||||
self.check_status()
|
|
||||||
60
main.py
60
main.py
@@ -1,37 +1,57 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from gui.main_window import MainWindow
|
from gui.main_window import MainWindow
|
||||||
|
|
||||||
def setup_logging():
|
def setup_logging():
|
||||||
"""设置日志"""
|
"""设置日志"""
|
||||||
log_dir = Path.home() / ".cursor_switcher" / "logs"
|
try:
|
||||||
log_dir.mkdir(parents=True, exist_ok=True)
|
log_dir = Path.home() / ".cursor_switcher" / "logs"
|
||||||
|
log_dir.mkdir(parents=True, exist_ok=True)
|
||||||
log_file = log_dir / "switcher.log"
|
|
||||||
|
log_file = log_dir / "switcher.log"
|
||||||
logging.basicConfig(
|
|
||||||
level=logging.INFO,
|
# 只输出到文件,不输出到控制台
|
||||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
logging.basicConfig(
|
||||||
handlers=[
|
level=logging.INFO,
|
||||||
logging.FileHandler(log_file, encoding="utf-8"),
|
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||||
logging.StreamHandler()
|
handlers=[
|
||||||
]
|
logging.FileHandler(log_file, encoding="utf-8"),
|
||||||
)
|
]
|
||||||
logging.info("日志系统初始化完成")
|
)
|
||||||
|
except Exception as e:
|
||||||
|
# 不打印错误信息,只记录到日志
|
||||||
|
pass
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""主函数"""
|
"""主函数"""
|
||||||
try:
|
try:
|
||||||
setup_logging()
|
setup_logging()
|
||||||
logging.info("启动GUI界面...")
|
|
||||||
|
# 检查Python版本
|
||||||
|
logging.info(f"Python版本: {sys.version}")
|
||||||
|
|
||||||
|
# 检查工作目录
|
||||||
|
logging.info(f"当前工作目录: {Path.cwd()}")
|
||||||
|
|
||||||
|
# 检查模块路径
|
||||||
|
logging.info("Python路径:")
|
||||||
|
for p in sys.path:
|
||||||
|
logging.info(f" - {p}")
|
||||||
|
|
||||||
|
logging.info("正在初始化主窗口...")
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
|
|
||||||
|
logging.info("正在启动主窗口...")
|
||||||
window.run()
|
window.run()
|
||||||
except KeyboardInterrupt:
|
|
||||||
logging.info("程序被用户中断")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"程序运行出错: {str(e)}")
|
error_msg = f"程序运行出错: {str(e)}\n{traceback.format_exc()}"
|
||||||
finally:
|
logging.error(error_msg)
|
||||||
logging.info("程序退出")
|
# 使用tkinter的消息框显示错误
|
||||||
|
from tkinter import messagebox
|
||||||
|
messagebox.showerror("错误", error_msg)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
pyinstaller==6.3.0
|
pyinstaller==6.3.0
|
||||||
|
pillow==10.2.0 # 用于处理图标
|
||||||
|
setuptools==65.5.1 # 解决pkg_resources.extern问题
|
||||||
72
utils/cursor_registry.py
Normal file
72
utils/cursor_registry.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import os
|
||||||
|
import winreg
|
||||||
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
class CursorRegistry:
|
||||||
|
"""Cursor注册表操作工具类"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.cursor_path = Path(os.path.expanduser("~")) / "AppData" / "Local" / "Programs" / "Cursor"
|
||||||
|
self.app_path = self.cursor_path / "resources" / "app"
|
||||||
|
|
||||||
|
def refresh_registry(self) -> bool:
|
||||||
|
"""刷新Cursor相关的注册表项
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 获取Cursor安装路径
|
||||||
|
cursor_exe = self.cursor_path / "Cursor.exe"
|
||||||
|
if not cursor_exe.exists():
|
||||||
|
logging.error("未找到Cursor.exe")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 刷新注册表项
|
||||||
|
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("注册表刷新成功")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except WindowsError as e:
|
||||||
|
logging.error(f"刷新注册表失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"刷新注册表过程出错: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def clean_registry(self) -> bool:
|
||||||
|
"""清理Cursor相关的注册表项
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
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
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"清理注册表过程出错: {str(e)}")
|
||||||
|
return False
|
||||||
Reference in New Issue
Block a user