feat(v3.4.7): 重构重置功能和优化重启逻辑

1. 新增 CursorResetter 类,完整封装 cursor_win_id_modifier.ps1 的核心功能

2. 优化 AccountSwitcher 的重启逻辑,避免重复重启

3. 改进进程管理,移除 wmi 依赖,使用 tasklist 替代

4. 提升代码可维护性,后续只需更新 CursorResetter 即可适配脚本变更
This commit is contained in:
huangzhenpc
2025-02-14 15:06:05 +08:00
parent 10523de040
commit 8b2fbef54a
9 changed files with 1322 additions and 437 deletions

114
main.py
View File

@@ -6,11 +6,13 @@ import atexit
import shutil
import tempfile
import urllib3
import ctypes
from pathlib import Path
from PyQt5.QtWidgets import QApplication, QMessageBox, QSystemTrayIcon, QMenu
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from gui.main_window import MainWindow
from account_switcher import AccountSwitcher
# 禁用所有 SSL 相关警告
urllib3.disable_warnings()
@@ -39,88 +41,114 @@ def setup_logging():
log_file = log_dir / "switcher.log"
# 输出到文件,不输出到控制台
# 同时输出到文件控制台
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler(log_file, encoding="utf-8"),
logging.StreamHandler()
]
)
except Exception as e:
# 不打印错误信息,只记录到日志
pass
print(f"设置日志失败: {str(e)}")
def is_admin():
"""检查是否具有管理员权限"""
try:
return ctypes.windll.shell32.IsUserAnAdmin() != 0
except:
return False
def run_as_admin():
"""以管理员权限重新运行程序"""
try:
if not is_admin():
# 获取当前脚本的路径
script = sys.argv[0]
params = ' '.join(sys.argv[1:])
# 以管理员权限重新运行
ctypes.windll.shell32.ShellExecuteW(
None,
"runas",
sys.executable,
f'"{script}" {params}',
None,
1
)
return True
except Exception as e:
print(f"提升权限失败: {str(e)}")
return False
def print_banner():
"""打印程序横幅"""
print("""
====================================
Cursor 账号管理工具
====================================
""")
def main():
"""主函数"""
try:
# 注册退出时的清理函数
# 1. 首先检查管理员权限
if not is_admin():
if run_as_admin():
return 0
else:
QMessageBox.critical(None, "错误", "需要管理员权限运行此程序。\n请右键点击程序,选择'以管理员身份运行'")
return 1
# 2. 注册退出时的清理函数
atexit.register(cleanup_temp)
# 创建QApplication实例
# 3. 设置日志
setup_logging()
# 4. 创建QApplication实例
app = QApplication(sys.argv)
# 检查系统托盘是否可用
# 5. 检查系统托盘
if not QSystemTrayIcon.isSystemTrayAvailable():
logging.error("系统托盘不可用")
QMessageBox.critical(None, "错误", "系统托盘不可用,程序无法正常运行。")
return 1
# 设置应用程序不会在最后一个窗口关闭时退出
# 6. 设置应用程序不会在最后一个窗口关闭时退出
app.setQuitOnLastWindowClosed(False)
setup_logging()
# 检查Python版本
# 7. 记录系统信息
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("正在初始化主窗口...")
# 设置应用程序ID (在设置图标之前)
# 8. 设置应用程序ID
if sys.platform == "win32":
import ctypes
myappid = u'nezha.cursor.helper.v3'
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
logging.info(f"设置应用程序ID: {myappid}")
# 设置应用程序图标
try:
icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon", "two.ico")
if os.path.exists(icon_path):
app_icon = QIcon(icon_path)
if not app_icon.isNull():
app.setWindowIcon(app_icon)
logging.info(f"成功设置应用程序图标: {icon_path}")
else:
logging.error("图标文件加载失败")
else:
logging.error(f"图标文件不存在: {icon_path}")
except Exception as e:
logging.error(f"设置应用程序图标失败: {str(e)}")
# 9. 设置应用程序图标
icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon", "two.ico")
if os.path.exists(icon_path):
app_icon = QIcon(icon_path)
if not app_icon.isNull():
app.setWindowIcon(app_icon)
logging.info(f"成功设置应用程序图标: {icon_path}")
# 10. 创建并显示主窗口
logging.info("正在初始化主窗口...")
window = MainWindow()
window.setWindowIcon(app.windowIcon()) # 确保窗口使用相同的图标
logging.info("正在启动主窗口...")
window.setWindowIcon(app.windowIcon())
window.show()
# 11. 运行应用程序
return app.exec_()
except Exception as e:
error_msg = f"程序运行出错: {str(e)}\n{traceback.format_exc()}"
logging.error(error_msg)
# 使用 QMessageBox 显示错误
if QApplication.instance() is None:
app = QApplication(sys.argv)
QMessageBox.critical(None, "错误", error_msg)
return 1