656863a7d0
* feat(docstring):添加docstring Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com> * fix(docstring):修复部分docstring格式错误 Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com> * fix(docstring):修复部分docstring Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com> * chore(Docstring):MW_* 前14 * chore(Docstring):MW_* part 2 * chore(Docstring):MW_* part 3 * chore:优化缩进 * fix: 修复数学计算中的潜在除零错误和数值稳定性问题 Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com> * chore:删除Rebase时多余的OOBE函数 * chore: 更新代码注释和文档格式 修复XML文档注释中的格式问题,统一使用<c>和<see>标签 更新ConfigHelper类的预留说明,明确未来扩展用途 优化TimerDisplayDate_Elapsed方法的注释,说明UI异步更新机制 合并重复的注释摘要行,提高文档可读性 添加形状识别功能的64位进程限制说明 修正视频呈现器设备选择逻辑的文档说明 * chore(IPPTLinkManager): 更新TryEndSlideShow方法的XML注释格式 * chore: 修正代码注释中的术语和格式问题 更新多个文件中的XML注释,统一使用<see langword="..."/>标记代替<c>...</c>标记 规范术语使用(如"延迟初始化"代替"懒惰初始化") 修正注释中的格式错误和补充说明 调整代码区域的注释对齐格式 --------- Signed-off-by: doudou0720 <98651603+doudou0720@users.noreply.github.com>
173 lines
7.1 KiB
C#
173 lines
7.1 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Threading;
|
|
|
|
namespace Ink_Canvas.Helpers
|
|
{
|
|
class LogHelper
|
|
{
|
|
public static string LogFile = "Log.txt";
|
|
private static string LogsFolder = "Logs";
|
|
private static string AppStartTime = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
|
|
private static readonly long MaxLogsFolderSizeBytes = 5 * 1024 * 1024; // 5MB
|
|
|
|
public static void NewLog(string str)
|
|
{
|
|
WriteLogToFile(str);
|
|
}
|
|
|
|
public static void NewLog(Exception ex)
|
|
{
|
|
if (ex == null) return;
|
|
var stackTrace = ex.StackTrace ?? "<no stack trace>";
|
|
var msg = $"[Exception] Type: {ex.GetType().FullName}\nMessage: {ex.Message}\nStackTrace: {stackTrace}";
|
|
if (ex.InnerException != null)
|
|
{
|
|
msg += $"\nInnerException: {ex.InnerException.GetType().FullName} - {ex.InnerException.Message}\n{ex.InnerException.StackTrace}";
|
|
}
|
|
WriteLogToFile(msg, LogType.Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将一条日志消息记录到应用的日志文件中(可能是单一日志文件或按启动时间存档的文件),同时在日志条目中包含时间戳、线程 ID 和调用者信息,并遵循应用的日志设置。
|
|
/// </summary>
|
|
/// <param name="str">要记录的日志文本消息。</param>
|
|
/// <param name="logType">日志的类型/等级,用于在日志条目中标识(例如 Info、Error、Warning 等)。</param>
|
|
public static void WriteLogToFile(string str, LogType logType = LogType.Info)
|
|
{
|
|
// 检查日志是否启用
|
|
if (MainWindow.Settings != null && MainWindow.Settings.Advanced != null && !MainWindow.Settings.Advanced.IsLogEnabled) return;
|
|
|
|
string strLogType = logType.ToString();
|
|
try
|
|
{
|
|
string file;
|
|
|
|
// 检查是否启用了日期保存功能
|
|
if (MainWindow.Settings != null && MainWindow.Settings.Advanced != null && MainWindow.Settings.Advanced.IsSaveLogByDate)
|
|
{
|
|
// 确保Logs文件夹存在
|
|
string logsPath = Path.Combine(App.RootPath, LogsFolder);
|
|
if (!Directory.Exists(logsPath))
|
|
{
|
|
Directory.CreateDirectory(logsPath);
|
|
}
|
|
|
|
// 检查Logs文件夹大小,如果超过5MB则清空
|
|
CheckAndCleanLogsFolder(logsPath);
|
|
|
|
// 使用软件启动时间作为日志文件名
|
|
file = Path.Combine(logsPath, $"Log_{AppStartTime}.txt");
|
|
}
|
|
else
|
|
{
|
|
file = App.RootPath + LogFile;
|
|
}
|
|
|
|
if (!Directory.Exists(App.RootPath))
|
|
{
|
|
ProcessProtectionManager.WithWriteAccess(App.RootPath, () => Directory.CreateDirectory(App.RootPath));
|
|
}
|
|
|
|
var threadId = Thread.CurrentThread.ManagedThreadId;
|
|
var callingMethod = new StackTrace(2, true).GetFrame(0);
|
|
string callerInfo = "<unknown>";
|
|
if (callingMethod != null)
|
|
{
|
|
var method = callingMethod.GetMethod();
|
|
if (method != null)
|
|
{
|
|
var className = method.DeclaringType != null ? method.DeclaringType.FullName : "<no class>";
|
|
callerInfo = $"{className}.{method.Name}";
|
|
}
|
|
}
|
|
string logLine = string.Format("{0} [T{1}] [{2}] [{3}] {4}", DateTime.Now.ToString("O"), threadId, strLogType, callerInfo, str);
|
|
ProcessProtectionManager.WithWriteAccess(file, () =>
|
|
{
|
|
using (StreamWriter sw = new StreamWriter(file, true))
|
|
{
|
|
sw.WriteLine(logLine);
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[LogHelper] WriteLogToFile failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查指定日志文件夹的总大小,并在超过 MaxLogsFolderSizeBytes 时删除该文件夹下的所有文件并记录清理日志。
|
|
/// </summary>
|
|
/// <param name="logsPath">要检查和清理的日志文件夹路径。</param>
|
|
/// <remarks>
|
|
/// - 如果目录不存在则直接返回。
|
|
/// - 当总大小超过 MaxLogsFolderSizeBytes 时,会尝试删除目录下的每个文件(单个删除失败将被忽略)。
|
|
/// - 清理完成后会向该目录下的 Log_{AppStartTime}.txt 写入一条带有时间戳和 [Cleanup] 标签的记录。
|
|
/// - 方法内部捕获并忽略所有异常以避免影响调用者流程。
|
|
/// </remarks>
|
|
private static void CheckAndCleanLogsFolder(string logsPath)
|
|
{
|
|
try
|
|
{
|
|
long totalSize = 0;
|
|
DirectoryInfo dirInfo = new DirectoryInfo(logsPath);
|
|
|
|
// 如果目录不存在,直接返回
|
|
if (!dirInfo.Exists) return;
|
|
|
|
// 计算文件夹大小
|
|
foreach (FileInfo file in dirInfo.GetFiles())
|
|
{
|
|
totalSize += file.Length;
|
|
}
|
|
|
|
// 如果超过5MB,清空文件夹
|
|
if (totalSize > MaxLogsFolderSizeBytes)
|
|
{
|
|
foreach (FileInfo file in dirInfo.GetFiles())
|
|
{
|
|
try
|
|
{
|
|
file.Delete();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[LogHelper] Delete log file failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
// 记录清理操作
|
|
string cleanupMessage = $"Logs folder exceeded size limit ({totalSize / 1024.0 / 1024.0:F2} MB > {MaxLogsFolderSizeBytes / 1024.0 / 1024.0:F2} MB). Folder cleaned.";
|
|
var logFile = Path.Combine(logsPath, $"Log_{AppStartTime}.txt");
|
|
ProcessProtectionManager.WithWriteAccess(logFile, () =>
|
|
{
|
|
using (StreamWriter sw = new StreamWriter(logFile, true))
|
|
{
|
|
sw.WriteLine($"{DateTime.Now:O} [Cleanup] {cleanupMessage}");
|
|
}
|
|
});
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"[LogHelper] CheckAndCleanLogsFolder failed: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
internal static void WriteLogToFile(string v, object warning)
|
|
{
|
|
WriteLogToFile($"[Warning] {v}", LogType.Warning);
|
|
}
|
|
|
|
public enum LogType
|
|
{
|
|
Info,
|
|
Trace,
|
|
Error,
|
|
Event,
|
|
Warning
|
|
}
|
|
}
|
|
} |