using Hardcodet.Wpf.TaskbarNotification; using Ink_Canvas.Helpers; using iNKORE.UI.WPF.Modern.Controls; using System; using System.Diagnostics; using System.Threading; using System.IO; using System.Linq; using System.Reflection; using System.Windows; using static System.Windows.Forms.VisualStyles.VisualStyleElement; using MessageBox = System.Windows.MessageBox; using Window = System.Windows.Window; namespace Ink_Canvas { /// /// Interaction logic for App.xaml /// public partial class App : Application { System.Threading.Mutex mutex; public static string[] StartArgs = null; public static string RootPath = Environment.GetEnvironmentVariable("APPDATA") + "\\Ink Canvas\\"; // 新增:保存看门狗进程对象 private static Process watchdogProcess = null; // 新增:标记是否为软件内主动退出 public static bool IsAppExitByUser = false; // 新增:退出信号文件路径 private static string watchdogExitSignalFile = Path.Combine(Path.GetTempPath(), "icc_watchdog_exit_" + System.Diagnostics.Process.GetCurrentProcess().Id + ".flag"); public App() { this.Startup += new StartupEventHandler(App_Startup); this.DispatcherUnhandledException += App_DispatcherUnhandledException; StartHeartbeatMonitor(); StartWatchdogIfNeeded(); this.Exit += App_Exit; // 注册退出事件 } // 增加字段保存崩溃后操作设置 public static CrashActionType CrashAction = CrashActionType.SilentRestart; private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { Ink_Canvas.MainWindow.ShowNewMessage("抱歉,出现未预期的异常,可能导致 InkCanvasForClass 运行不稳定。\n建议保存墨迹后重启应用。", true); LogHelper.NewLog(e.Exception.ToString()); e.Handled = true; // 新增:根据设置自动处理崩溃 if (CrashAction == CrashActionType.SilentRestart) { try { // 静默重启:启动新进程并退出当前进程 string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; System.Diagnostics.Process.Start(exePath); } catch { } Environment.Exit(1); } // CrashActionType.NoAction 时不做处理 } private TaskbarIcon _taskbar; void App_Startup(object sender, StartupEventArgs e) { RunWatchdogIfNeeded(); /*if (!StoreHelper.IsStoreApp) */RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; LogHelper.NewLog(string.Format("Ink Canvas Starting (Version: {0})", Assembly.GetExecutingAssembly().GetName().Version.ToString())); bool ret; mutex = new System.Threading.Mutex(true, "InkCanvasForClass", out ret); if (!ret && !e.Args.Contains("-m")) //-m multiple { LogHelper.NewLog("Detected existing instance"); MessageBox.Show("已有一个程序实例正在运行"); LogHelper.NewLog("Ink Canvas automatically closed"); Environment.Exit(0); } _taskbar = (TaskbarIcon)FindResource("TaskbarTrayIcon"); StartArgs = e.Args; } private void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) { try { if (System.Windows.Forms.SystemInformation.MouseWheelScrollLines == -1) e.Handled = false; else try { ScrollViewerEx SenderScrollViewer = (ScrollViewerEx)sender; SenderScrollViewer.ScrollToVerticalOffset(SenderScrollViewer.VerticalOffset - e.Delta * 10 * System.Windows.Forms.SystemInformation.MouseWheelScrollLines / (double)120); e.Handled = true; } catch { } } catch { } } // 新增:用于设置崩溃后操作类型 public enum CrashActionType { SilentRestart, NoAction } // 心跳相关 private static Timer heartbeatTimer; private static DateTime lastHeartbeat = DateTime.Now; private static Timer watchdogTimer; private void StartHeartbeatMonitor() { // 主线程定时更新心跳 heartbeatTimer = new Timer(_ => lastHeartbeat = DateTime.Now, null, 0, 1000); // 辅助线程检测心跳超时 watchdogTimer = new Timer(_ => { if ((DateTime.Now - lastHeartbeat).TotalSeconds > 10) { LogHelper.NewLog("检测到主线程无响应,自动重启。"); if (CrashAction == CrashActionType.SilentRestart) { try { string exePath = Process.GetCurrentProcess().MainModule.FileName; Process.Start(exePath); } catch { } Environment.Exit(1); } } }, null, 0, 3000); } // 看门狗进程 private void StartWatchdogIfNeeded() { // 避免递归启动 if (Environment.GetCommandLineArgs().Contains("--watchdog")) return; // 启动看门狗进程 string exePath = Process.GetCurrentProcess().MainModule.FileName; var psi = new ProcessStartInfo { FileName = exePath, Arguments = "--watchdog " + Process.GetCurrentProcess().Id + " \"" + watchdogExitSignalFile + "\"", CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden }; watchdogProcess = Process.Start(psi); } // 看门狗主逻辑(在 Main 函数或 App_Startup 入口前加判断) public static void RunWatchdogIfNeeded() { var args = Environment.GetCommandLineArgs(); if (args.Length >= 4 && args[1] == "--watchdog") { int pid = int.Parse(args[2]); string exitSignalFile = args[3]; try { var proc = Process.GetProcessById(pid); while (!proc.HasExited) { // 检查退出信号文件 if (File.Exists(exitSignalFile)) { try { File.Delete(exitSignalFile); } catch { } Environment.Exit(0); } Thread.Sleep(2000); } // 主进程异常退出,自动重启 string exePath = Process.GetCurrentProcess().MainModule.FileName; Process.Start(exePath); } catch { } Environment.Exit(0); } } private void App_Exit(object sender, ExitEventArgs e) { // 仅在软件内主动退出时关闭看门狗,并写入退出信号 try { if (IsAppExitByUser) { // 写入退出信号文件,通知看门狗正常退出 File.WriteAllText(watchdogExitSignalFile, "exit"); if (watchdogProcess != null && !watchdogProcess.HasExited) { watchdogProcess.Kill(); } } } catch { } } } }