mirror of
https://github.com/hyb-oyqq/FRAISEMOE-Addons-Installer-NEXT.git
synced 2026-01-01 11:40:45 +00:00
feat(core): 增强日志记录和错误处理功能
- 更新日志记录机制,将日志文件存储在程序根目录下的log文件夹中,并使用日期+时间戳格式命名。 - 在多个模块中添加详细的错误处理逻辑,确保在发生异常时能够记录相关信息,便于后续排查。 - 优化UI管理器中的日志文件打开功能,增加对日志文件存在性和大小的检查,提升用户体验。 - 在下载管理器和补丁管理器中增强调试信息的记录,确保在关键操作中提供更清晰的反馈。
This commit is contained in:
@@ -175,6 +175,12 @@ class HashManager:
|
||||
|
||||
try:
|
||||
expected_hash = plugin_hash.get(game_version, "")
|
||||
if not expected_hash:
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 哈希预检查 - {game_version} 没有预期哈希值,跳过哈希检查")
|
||||
# 当没有预期哈希值时,保持当前状态不变
|
||||
continue
|
||||
|
||||
file_hash = self.hash_calculate(install_path)
|
||||
|
||||
if debug_mode:
|
||||
@@ -186,8 +192,12 @@ class HashManager:
|
||||
|
||||
if file_hash == expected_hash:
|
||||
status_copy[game_version] = True
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 哈希预检查 - {game_version} 哈希匹配成功")
|
||||
else:
|
||||
status_copy[game_version] = False
|
||||
if debug_mode:
|
||||
logger.debug(f"DEBUG: 哈希预检查 - {game_version} 哈希不匹配")
|
||||
except Exception as e:
|
||||
status_copy[game_version] = False
|
||||
if debug_mode:
|
||||
@@ -270,65 +280,98 @@ class AdminPrivileges:
|
||||
"\n需要管理员权限运行此程序\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
)
|
||||
reply = msg_box.exec()
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
try:
|
||||
ctypes.windll.shell32.ShellExecuteW(
|
||||
None, "runas", sys.executable, " ".join(sys.argv), None, 1
|
||||
)
|
||||
except Exception as e:
|
||||
try:
|
||||
reply = msg_box.exec()
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
try:
|
||||
ctypes.windll.shell32.ShellExecuteW(
|
||||
None, "runas", sys.executable, " ".join(sys.argv), None, 1
|
||||
)
|
||||
except Exception as e:
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n请求管理员权限失败\n\n【错误信息】:{e}\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
else:
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n请求管理员权限失败\n\n【错误信息】:{e}\n",
|
||||
f"权限检测 - {APP_NAME}",
|
||||
"\n无法获取管理员权限,程序将退出\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
logger.warning("管理员权限请求被用户中断")
|
||||
msg_box = msgbox_frame(
|
||||
f"权限检测 - {APP_NAME}",
|
||||
"\n无法获取管理员权限,程序将退出\n",
|
||||
"\n操作被中断,程序将退出\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
logger.error(f"管理员权限请求时发生错误: {e}")
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n请求管理员权限时发生未知错误\n\n【错误信息】:{e}\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
|
||||
def check_and_terminate_processes(self):
|
||||
for proc in psutil.process_iter(["pid", "name"]):
|
||||
proc_name = proc.info["name"].lower() if proc.info["name"] else ""
|
||||
|
||||
# 检查进程名是否匹配任何需要终止的游戏进程
|
||||
for exe in self.required_exes:
|
||||
if exe.lower() == proc_name:
|
||||
# 获取不带.nocrack的游戏名称用于显示
|
||||
display_name = exe.replace(".nocrack", "")
|
||||
|
||||
msg_box = msgbox_frame(
|
||||
f"进程检测 - {APP_NAME}",
|
||||
f"\n检测到游戏正在运行: {display_name} \n\n是否终止?\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
)
|
||||
reply = msg_box.exec()
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
try:
|
||||
proc.terminate()
|
||||
proc.wait(timeout=3)
|
||||
except psutil.AccessDenied:
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n无法关闭游戏: {display_name} \n\n请手动关闭后重启应用\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
else:
|
||||
try:
|
||||
for proc in psutil.process_iter(["pid", "name"]):
|
||||
proc_name = proc.info["name"].lower() if proc.info["name"] else ""
|
||||
|
||||
# 检查进程名是否匹配任何需要终止的游戏进程
|
||||
for exe in self.required_exes:
|
||||
if exe.lower() == proc_name:
|
||||
# 获取不带.nocrack的游戏名称用于显示
|
||||
display_name = exe.replace(".nocrack", "")
|
||||
|
||||
msg_box = msgbox_frame(
|
||||
f"进程检测 - {APP_NAME}",
|
||||
f"\n未关闭的游戏: {display_name} \n\n请手动关闭后重启应用\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
f"\n检测到游戏正在运行: {display_name} \n\n是否终止?\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
try:
|
||||
reply = msg_box.exec()
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
try:
|
||||
proc.terminate()
|
||||
proc.wait(timeout=3)
|
||||
except psutil.AccessDenied:
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n无法关闭游戏: {display_name} \n\n请手动关闭后重启应用\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
else:
|
||||
msg_box = msgbox_frame(
|
||||
f"进程检测 - {APP_NAME}",
|
||||
f"\n未关闭的游戏: {display_name} \n\n请手动关闭后重启应用\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
except KeyboardInterrupt:
|
||||
logger.warning(f"进程 {display_name} 终止操作被用户中断")
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"进程 {display_name} 终止操作时发生错误: {e}")
|
||||
raise
|
||||
except KeyboardInterrupt:
|
||||
logger.warning("进程检查被用户中断")
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"进程检查时发生错误: {e}")
|
||||
raise
|
||||
|
||||
class HostsManager:
|
||||
def __init__(self):
|
||||
|
||||
@@ -9,26 +9,58 @@ class URLCensorFormatter(logging.Formatter):
|
||||
def format(self, record):
|
||||
# 先使用原始的format方法格式化日志
|
||||
formatted_message = super().format(record)
|
||||
# 然后对格式化后的消息进行URL审查
|
||||
return censor_url(formatted_message)
|
||||
# 临时禁用URL隐藏,直接返回原始消息
|
||||
return formatted_message
|
||||
# 然后对格式化后的消息进行URL审查(已禁用)
|
||||
# return censor_url(formatted_message)
|
||||
|
||||
class Logger:
|
||||
def __init__(self, filename, stream):
|
||||
self.terminal = stream
|
||||
self.log = open(filename, "w", encoding="utf-8")
|
||||
try:
|
||||
# 确保目录存在
|
||||
log_dir = os.path.dirname(filename)
|
||||
if log_dir and not os.path.exists(log_dir):
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
print(f"已创建日志目录: {log_dir}")
|
||||
|
||||
# 以追加模式打开,避免覆盖现有内容
|
||||
self.log = open(filename, "a", encoding="utf-8", errors="replace")
|
||||
self.log.write("\n\n--- New logging session started ---\n\n")
|
||||
except (IOError, OSError) as e:
|
||||
# 如果打开文件失败,记录错误并使用空的写入操作
|
||||
print(f"Error opening log file {filename}: {e}")
|
||||
self.log = None
|
||||
|
||||
def write(self, message):
|
||||
censored_message = censor_url(message)
|
||||
self.terminal.write(censored_message)
|
||||
self.log.write(censored_message)
|
||||
self.flush()
|
||||
try:
|
||||
# 临时禁用URL隐藏
|
||||
# censored_message = censor_url(message)
|
||||
censored_message = message # 直接使用原始消息
|
||||
self.terminal.write(censored_message)
|
||||
if self.log:
|
||||
self.log.write(censored_message)
|
||||
self.flush()
|
||||
except Exception as e:
|
||||
# 发生错误时记录到控制台
|
||||
self.terminal.write(f"Error writing to log: {e}\n")
|
||||
|
||||
def flush(self):
|
||||
self.terminal.flush()
|
||||
self.log.flush()
|
||||
try:
|
||||
self.terminal.flush()
|
||||
if self.log:
|
||||
self.log.flush()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
self.log.close()
|
||||
try:
|
||||
if self.log:
|
||||
self.log.write("\n--- Logging session ended ---\n")
|
||||
self.log.close()
|
||||
self.log = None
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def setup_logger(name):
|
||||
"""设置并返回一个命名的logger
|
||||
@@ -39,6 +71,9 @@ def setup_logger(name):
|
||||
Returns:
|
||||
logging.Logger: 配置好的logger对象
|
||||
"""
|
||||
# 导入LOG_FILE
|
||||
from data.config import LOG_FILE
|
||||
|
||||
# 创建logger
|
||||
logger = logging.getLogger(name)
|
||||
|
||||
@@ -53,10 +88,24 @@ def setup_logger(name):
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
log_file = os.path.join(log_dir, f"{name}.log")
|
||||
|
||||
# 创建文件处理器
|
||||
# 创建文件处理器 - 模块日志
|
||||
file_handler = logging.FileHandler(log_file, encoding="utf-8")
|
||||
file_handler.setLevel(logging.DEBUG)
|
||||
|
||||
# 创建主日志文件处理器 - 所有日志合并到主LOG_FILE
|
||||
try:
|
||||
# 确保主日志文件目录存在
|
||||
log_file_dir = os.path.dirname(LOG_FILE)
|
||||
if log_file_dir and not os.path.exists(log_file_dir):
|
||||
os.makedirs(log_file_dir, exist_ok=True)
|
||||
print(f"已创建主日志目录: {log_file_dir}")
|
||||
|
||||
main_file_handler = logging.FileHandler(LOG_FILE, encoding="utf-8", mode="w")
|
||||
main_file_handler.setLevel(logging.DEBUG)
|
||||
except (IOError, OSError) as e:
|
||||
print(f"无法创建主日志文件处理器: {e}")
|
||||
main_file_handler = None
|
||||
|
||||
# 创建控制台处理器
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setLevel(logging.INFO)
|
||||
@@ -65,9 +114,13 @@ def setup_logger(name):
|
||||
formatter = URLCensorFormatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
file_handler.setFormatter(formatter)
|
||||
console_handler.setFormatter(formatter)
|
||||
if main_file_handler:
|
||||
main_file_handler.setFormatter(formatter)
|
||||
|
||||
# 添加处理器到logger
|
||||
logger.addHandler(file_handler)
|
||||
logger.addHandler(console_handler)
|
||||
if main_file_handler:
|
||||
logger.addHandler(main_file_handler)
|
||||
|
||||
return logger
|
||||
@@ -9,9 +9,25 @@ def censor_url(text):
|
||||
Returns:
|
||||
str: 处理后的文本,URL被完全隐藏
|
||||
"""
|
||||
# 临时禁用URL隐藏功能,直接返回原始文本以便调试
|
||||
if not isinstance(text, str):
|
||||
text = str(text)
|
||||
|
||||
return text # 直接返回原始文本,不做任何隐藏
|
||||
|
||||
# 以下是原始代码,现在被注释掉
|
||||
'''
|
||||
# 匹配URL并替换为固定文本
|
||||
url_pattern = re.compile(r'https?://[^\s/$.?#].[^\s]*')
|
||||
return url_pattern.sub('***URL protection***', text)
|
||||
censored = url_pattern.sub('***URL protection***', text)
|
||||
|
||||
# 额外处理带referer参数的情况
|
||||
referer_pattern = re.compile(r'--referer\s+(\S+)')
|
||||
censored = referer_pattern.sub('--referer ***URL protection***', censored)
|
||||
|
||||
# 处理Origin头
|
||||
origin_pattern = re.compile(r'Origin:\s+(\S+)')
|
||||
censored = origin_pattern.sub('Origin: ***URL protection***', censored)
|
||||
|
||||
return censored
|
||||
'''
|
||||
Reference in New Issue
Block a user