fix: 移除崩溃弹窗机制

This commit is contained in:
DLmaster361
2025-07-19 22:23:59 +08:00
parent eb1fade6f5
commit 97c283797a
3 changed files with 27 additions and 249 deletions

267
main.py
View File

@@ -25,50 +25,6 @@ v4.4
作者DLmaster_361
"""
import os
import sys
# Nuitka环境检测和修复
def setup_nuitka_compatibility():
"""设置Nuitka打包环境的兼容性"""
# 检测打包环境
is_nuitka = (
hasattr(sys, "frozen")
or "nuitka" in sys.modules
or "Temp\\AUTO_MAA" in str(sys.executable)
or os.path.basename(sys.executable) == "AUTO_MAA.exe"
)
if is_nuitka:
# 修复PySide6 QTimer问题
try:
from PySide6.QtCore import QTimer
original_singleShot = QTimer.singleShot
@staticmethod
def safe_singleShot(*args, **kwargs):
if len(args) >= 2:
msec = args[0]
callback = args[-1]
# 确保使用正确的调用签名
return original_singleShot(msec, callback)
return original_singleShot(*args, **kwargs)
QTimer.singleShot = safe_singleShot
except Exception as e:
pass
# 立即应用兼容性修复
setup_nuitka_compatibility()
# 屏蔽广告
import builtins
@@ -88,11 +44,14 @@ def no_print(*args, **kwargs):
builtins.print = no_print
import os
import sys
import ctypes
import traceback
from PySide6.QtWidgets import QApplication
from qfluentwidgets import FluentTranslator
from app.core.logger import logger
def is_admin() -> bool:
"""检查当前程序是否以管理员身份运行"""
@@ -102,214 +61,28 @@ def is_admin() -> bool:
return False
def show_system_error(title: str, message: str, detailed_error: str = None):
"""使用系统级消息框显示错误"""
try:
# Windows系统消息框
if sys.platform == "win32":
# 组合完整的错误信息
full_message = message
if detailed_error:
# 限制详细错误信息长度,避免消息框过大
if len(detailed_error) > 2000:
detailed_error = (
detailed_error[:2000] + "\n\n... (错误信息过长已截断)"
)
full_message += f"\n\n详细错误信息:\n{detailed_error}"
# 使用ctypes调用Windows API
ctypes.windll.user32.MessageBoxW(
0, # 父窗口句柄
full_message, # 消息内容
title, # 标题
0x10 | 0x0, # MB_ICONERROR | MB_OK
)
# Linux系统 - 尝试使用zenity或kdialog
elif sys.platform.startswith("linux"):
full_message = message
if detailed_error:
full_message += f"\n\n详细错误:\n{detailed_error[:1000]}"
try:
# 尝试zenity (GNOME)
os.system(
f'zenity --error --title="{title}" --text="{full_message}" 2>/dev/null'
)
except:
try:
# 尝试kdialog (KDE)
os.system(
f'kdialog --error "{full_message}" --title "{title}" 2>/dev/null'
)
except:
# 降级到控制台输出
print(f"错误: {title}")
print(f"消息: {message}")
if detailed_error:
print(f"详细信息:\n{detailed_error}")
# macOS系统
elif sys.platform == "darwin":
full_message = message
if detailed_error:
full_message += f"\n\n详细错误:\n{detailed_error[:1000]}"
try:
os.system(
f'osascript -e \'display alert "{title}" message "{full_message}" as critical\''
)
except:
print(f"错误: {title}")
print(f"消息: {message}")
if detailed_error:
print(f"详细信息:\n{detailed_error}")
else:
# 其他系统降级到控制台输出
print(f"错误: {title}")
print(f"消息: {message}")
if detailed_error:
print(f"详细信息:\n{detailed_error}")
except Exception as e:
# 如果连系统消息框都失败了,输出到控制台
print(f"无法显示错误对话框: {e}")
print(f"原始错误: {title} - {message}")
if detailed_error:
print(f"详细错误信息:\n{detailed_error}")
def save_error_log(error_info: str):
"""保存错误日志到文件"""
try:
import datetime
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
log_dir = os.path.join(os.path.dirname(__file__), "debug")
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, f"crash_{timestamp}.log")
with open(log_file, "w", encoding="utf-8") as f:
f.write(f"AUTO_MAA 崩溃日志\n")
f.write(f"时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"Python版本: {sys.version}\n")
f.write(f"平台: {sys.platform}\n")
f.write(f"工作目录: {os.getcwd()}\n")
f.write("=" * 50 + "\n")
f.write(error_info)
return log_file
except:
return None
@logger.catch
def main():
"""主程序入口"""
application = None
try:
# 创建QApplication
application = QApplication(sys.argv)
application = QApplication(sys.argv)
# 安装翻译器
translator = FluentTranslator()
application.installTranslator(translator)
translator = FluentTranslator()
application.installTranslator(translator)
try:
# 导入主窗口模块
from app.ui.main_window import AUTO_MAA
from app.ui.main_window import AUTO_MAA
# 创建主窗口
window = AUTO_MAA()
window.show_ui("显示主窗口", if_start=True)
window.start_up_task()
except ImportError as e:
error_msg = f"模块导入失败: {str(e)}"
detailed_error = traceback.format_exc()
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
if log_file:
error_msg += f"\n\n错误日志已保存到: {log_file}"
show_system_error("模块导入错误", error_msg, detailed_error)
return
except Exception as e:
error_msg = f"主窗口创建失败: {str(e)}"
detailed_error = traceback.format_exc()
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
if log_file:
error_msg += f"\n\n错误日志已保存到: {log_file}"
show_system_error("窗口创建错误", error_msg, detailed_error)
return
# 启动事件循环
sys.exit(application.exec())
except Exception as e:
error_msg = f"应用程序启动失败: {str(e)}"
detailed_error = traceback.format_exc()
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
if log_file:
error_msg += f"\n\n错误日志已保存到: {log_file}"
# 尝试显示错误对话框
show_system_error("应用程序启动错误", error_msg, detailed_error)
# 如果有应用程序实例,确保正确退出
if application:
try:
application.quit()
except:
pass
sys.exit(1)
def handle_exception(exc_type, exc_value, exc_traceback):
"""全局异常处理器"""
if issubclass(exc_type, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_value, exc_traceback)
return
error_msg = f"未处理的异常: {exc_type.__name__}: {str(exc_value)}"
detailed_error = "".join(
traceback.format_exception(exc_type, exc_value, exc_traceback)
)
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
if log_file:
error_msg += f"\n\n错误日志已保存到: {log_file}"
show_system_error("程序异常", error_msg, detailed_error)
# 设置全局异常处理器
sys.excepthook = handle_exception
window = AUTO_MAA()
window.show_ui("显示主窗口", if_start=True)
window.start_up_task()
sys.exit(application.exec())
if __name__ == "__main__":
try:
if is_admin():
main()
else:
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, os.path.realpath(sys.argv[0]), None, 1
)
sys.exit(0)
except Exception as e:
error_msg = f"程序启动失败: {str(e)}"
detailed_error = traceback.format_exc()
log_file = save_error_log(f"{error_msg}\n\n{detailed_error}")
if log_file:
error_msg += f"\n\n错误日志已保存到: {log_file}"
show_system_error("启动错误", error_msg, detailed_error)
sys.exit(1)
if is_admin():
main()
else:
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, os.path.realpath(sys.argv[0]), None, 1
)
sys.exit(0)