1. 新增 CursorResetter 类,完整封装 cursor_win_id_modifier.ps1 的核心功能 2. 优化 AccountSwitcher 的重启逻辑,避免重复重启 3. 改进进程管理,移除 wmi 依赖,使用 tasklist 替代 4. 提升代码可维护性,后续只需更新 CursorResetter 即可适配脚本变更
156 lines
4.7 KiB
Python
156 lines
4.7 KiB
Python
import logging
|
|
import sys
|
|
import traceback
|
|
import os
|
|
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()
|
|
logging.getLogger('urllib3').setLevel(logging.ERROR)
|
|
|
|
def cleanup_temp():
|
|
"""清理临时文件"""
|
|
try:
|
|
temp_dir = Path(tempfile._get_default_tempdir())
|
|
for item in temp_dir.glob('_MEI*'):
|
|
try:
|
|
if item.is_dir():
|
|
shutil.rmtree(str(item), ignore_errors=True)
|
|
elif item.is_file():
|
|
item.unlink()
|
|
except:
|
|
pass
|
|
except:
|
|
pass
|
|
|
|
def setup_logging():
|
|
"""设置日志"""
|
|
try:
|
|
log_dir = Path.home() / ".cursor_switcher" / "logs"
|
|
log_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
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:
|
|
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)
|
|
|
|
# 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)
|
|
|
|
# 7. 记录系统信息
|
|
logging.info(f"Python版本: {sys.version}")
|
|
logging.info(f"当前工作目录: {Path.cwd()}")
|
|
|
|
# 8. 设置应用程序ID
|
|
if sys.platform == "win32":
|
|
myappid = u'nezha.cursor.helper.v3'
|
|
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
|
|
logging.info(f"设置应用程序ID: {myappid}")
|
|
|
|
# 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())
|
|
window.show()
|
|
|
|
# 11. 运行应用程序
|
|
return app.exec_()
|
|
|
|
except Exception as e:
|
|
error_msg = f"程序运行出错: {str(e)}\n{traceback.format_exc()}"
|
|
logging.error(error_msg)
|
|
QMessageBox.critical(None, "错误", error_msg)
|
|
return 1
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |