Files
nezhacursor/main.py
2025-02-14 16:15:04 +08:00

185 lines
5.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import logging
import sys
import traceback
import os
import atexit
import shutil
import tempfile
import urllib3
import ctypes
import win32event
import win32api
import winerror
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 prevent_multiple_instances():
"""防止程序多开
Returns:
bool: 如果是第一个实例返回True否则返回False
"""
try:
# 创建一个唯一的互斥锁名称
mutex_name = "Global\\CursorHelper_SingleInstance_Lock"
# 尝试创建互斥锁
handle = win32event.CreateMutex(None, 1, mutex_name)
if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
# 互斥锁已存在,说明程序已经在运行
logging.warning("程序已经在运行")
QMessageBox.warning(None, "警告", "程序已经在运行!\n请不要重复打开程序。")
return False
return True
except Exception as e:
logging.error(f"检查程序实例失败: {str(e)}")
return True # 如果检查失败,允许程序运行
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:
# 0. 检查是否已有实例在运行
if not prevent_multiple_instances():
return 1
# 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())