NewLife/XCoder

Linux版添加文本控件日志绑定、全局异常拦截
笑笑 authored at 2019-10-25 00:44:29
ffdd2e9
Tree
1 Parent(s) 314cd8e
Summary: 3 changed files with 174 additions and 1 deletions.
Added +40 -0
Added +131 -0
Modified +3 -1
Added +40 -0
diff --git a/XCoderLinux/Log/TextControlLog.cs b/XCoderLinux/Log/TextControlLog.cs
new file mode 100644
index 0000000..d268cd7
--- /dev/null
+++ b/XCoderLinux/Log/TextControlLog.cs
@@ -0,0 +1,40 @@
+using System;
+using Gtk;
+
+namespace NewLife.Log
+{
+    /// <summary>文本控件输出日志</summary>
+    public class TextControlLog : Logger
+    {
+        /// <summary>文本控件</summary>
+        public TextView Control { get; set; }
+
+        /// <summary>最大行数,超过该行数讲清空文本控件。默认1000行</summary>
+        public Int32 MaxLines { get; set; } = 1000;
+
+        /// <summary>写日志</summary>
+        /// <param name="level"></param>
+        /// <param name="format"></param>
+        /// <param name="args"></param>
+        protected override void OnWrite(LogLevel level, String format, params Object[] args)
+        {
+            WriteLog(Control, Format(format, args) + Environment.NewLine, MaxLines);
+        }
+
+        /// <summary>在WinForm控件上输出日志,主要考虑非UI线程操作</summary>
+        /// <remarks>不是常用功能,为了避免干扰常用功能,保持UseWinForm开头</remarks>
+        /// <param name="control">要绑定日志输出的WinForm控件</param>
+        /// <param name="msg">日志</param>
+        /// <param name="maxLines">最大行数</param>
+        public static void WriteLog(TextView control, String msg, Int32 maxLines = 1000)
+        {
+            if (control == null) return;
+
+            var txt = control; //as TextBoxBase;
+            if (txt == null) throw new XException("不支持的控件类型{0}!", control.GetType());
+
+            var textIter = txt.Buffer.EndIter;
+            txt.Buffer.Insert(ref textIter, msg);
+        }
+    }
+}
\ No newline at end of file
Added +131 -0
diff --git a/XCoderLinux/Log/XTrace.cs b/XCoderLinux/Log/XTrace.cs
new file mode 100644
index 0000000..104d849
--- /dev/null
+++ b/XCoderLinux/Log/XTrace.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Reflection;
+using System.Runtime.Versioning;
+using System.Threading;
+using System.Threading.Tasks;
+using GLib;
+using Gtk;
+using NewLife.Reflection;
+using NewLife.Threading;
+using Object = System.Object;
+
+namespace NewLife.Log
+{
+    /// <summary>日志类,包含跟踪调试功能</summary>
+    /// <remarks>
+    /// 该静态类包括写日志、写调用栈和Dump进程内存等调试功能。
+    /// 
+    /// 默认写日志到文本文件,可通过修改<see cref="NewLife.Log"/>属性来增加日志输出方式。
+    /// 对于控制台工程,可以直接通过UseConsole方法,把日志输出重定向为控制台输出,并且可以为不同线程使用不同颜色。
+    /// </remarks>
+    public static partial class XTrace2
+    {
+        #region 拦截WinForm异常
+        private static Int32 initWF = 0;
+        private static Boolean _ShowErrorMessage;
+
+        private static Window _window;
+        //private static String _Title;
+
+        /// <summary>拦截WinForm异常并记录日志,可指定是否用<see cref="MessageBox"/>显示。</summary>
+        /// <param name="showErrorMessage">发为捕获异常时,是否显示提示,默认显示</param>
+        public static void UseWinForm(Window window, Boolean showErrorMessage = true)
+        {
+            Runtime.IsConsole = false;
+
+            _window = window;
+            _ShowErrorMessage = showErrorMessage;
+
+            if (initWF > 0 || Interlocked.CompareExchange(ref initWF, 1, 0) != 0) return;
+            //if (!Application.MessageLoop) return;
+
+            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException2;
+            ExceptionManager.UnhandledException += ExceptionManager_UnhandledException;
+            //Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
+            //Application.ThreadException += Application_ThreadException;
+        }
+
+        private static void ExceptionManager_UnhandledException(UnhandledExceptionArgs e)
+        { 
+            var show = _ShowErrorMessage;
+            var ex = e.ExceptionObject as Exception;
+            var title = e.IsTerminating ? "异常退出" : "出错";
+            if (show)
+            {
+                var md = new MessageDialog(_window,
+                    DialogFlags.DestroyWithParent, MessageType.Error,
+                    ButtonsType.None, ex?.Message);
+                md.Run();
+                md.Dispose();
+            }
+
+        }
+
+        static void CurrentDomain_UnhandledException2(Object sender, UnhandledExceptionEventArgs e)
+        {
+            //var show = _ShowErrorMessage && Application.MessageLoop;
+            //var ex = e.ExceptionObject as Exception;
+            //var title = e.IsTerminating ? "异常退出" : "出错";
+            //if (show) MessageBox.Show(ex?.Message, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
+        }
+
+        static void Application_ThreadException(Object sender, ThreadExceptionEventArgs e)
+        {
+            //XTrace.WriteException(e.Exception);
+
+            //var show = _ShowErrorMessage && Application.MessageLoop;
+            //if (show) MessageBox.Show(e.Exception == null ? "" : e.Exception.Message, "出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
+        }
+
+        /// <summary>在WinForm控件上输出日志,主要考虑非UI线程操作</summary>
+        /// <remarks>不是常用功能,为了避免干扰常用功能,保持UseWinForm开头</remarks>
+        /// <param name="control">要绑定日志输出的WinForm控件</param>
+        /// <param name="useFileLog">是否同时使用文件日志,默认使用</param>
+        /// <param name="maxLines">最大行数</param>
+        public static void UseWinFormControl(this TextView control, Boolean useFileLog = true, Int32 maxLines = 1000)
+        {
+            var clg = XTrace.Log as TextControlLog;
+            var ftl = XTrace.Log as TextFileLog;
+            if (XTrace.Log is CompositeLog cmp)
+            {
+                ftl = cmp.Get<TextFileLog>();
+                clg = cmp.Get<TextControlLog>();
+            }
+
+            // 控制控制台日志
+            if (clg == null) clg = new TextControlLog();
+            clg.Control = control;
+            clg.MaxLines = maxLines;
+
+            if (!useFileLog)
+            {
+                XTrace.Log = clg;
+                if (ftl != null) ftl.Dispose();
+            }
+            else
+            {
+                if (ftl == null) ftl = TextFileLog.Create(null);
+                XTrace.Log = new CompositeLog(clg, ftl);
+            }
+        }
+
+        /// <summary>控件绑定到日志,生成混合日志</summary>
+        /// <param name="control"></param>
+        /// <param name="log"></param>
+        /// <param name="maxLines"></param>
+        /// <returns></returns>
+        public static ILog Combine(this TextView control, ILog log, Int32 maxLines = 1000)
+        {
+            if (control == null || log == null) return log;
+
+            var clg = new TextControlLog
+            {
+                Control = control,
+                MaxLines = maxLines
+            };
+
+            return new CompositeLog(log, clg);
+        }
+        #endregion
+    }
+}
\ No newline at end of file
Modified +3 -1
diff --git a/XCoderLinux/Program.cs b/XCoderLinux/Program.cs
index 1257014..549741a 100644
--- a/XCoderLinux/Program.cs
+++ b/XCoderLinux/Program.cs
@@ -1,5 +1,6 @@
 using System;
 using Gtk;
+using NewLife.Log;
 
 namespace XCoder
 {
@@ -12,8 +13,9 @@ namespace XCoder
         static void Main()
         {
             Application.Init();
-            new SharpApp();
+            var window = new SharpApp();
             Window.InteractiveDebugging = true;//打开调试工具
+            XTrace2.UseWinForm(window);
             Application.Run();
         }
     }