WPF 自定義日志記錄


為了便於分析應用程序的運行情況和BUG診斷,一般都會搞個日志輸出。
當初看過一點Log4net,覺得有些麻煩了,就動手寫了個簡單的。
本例子已經在 項目中使用過,拿出來分享一下,歡迎各位拍磚,呵呵。
本日志記錄比較輕巧,在config文件里面配置后,把loghelper.cs 文件放到項目中即可使用。日志輸出開關有四個:不輸出、輸出到DebugVIew、每次全新輸出到文本、追加輸出到文本。
輸出的日志有特定的分隔符,可以放到excel里面,分割為每一列后繼續進行篩選等分析。

本例子運行環境是DoNet 3.5 WPF C#,也可以擴展到別的環境使用.

 

效果預覽

 

 

 

配置文件

當初想過使用ini文件或者xml文件存儲配置信息,后來發現config文件用的比較多,而且config文件讀取比較方便,索性就集成到Config文件里面。

在項目里面添加config文件即可。

 1 <?xml version="1.0" encoding="utf-8" ?>
2 <!-- Author Shi Xiaokang
3 http://www.cnblogs.com/xiaokang088/
4 Version 1.00
5 Date: 2011-1-21-->
6 <configuration>
7 <runtime>
8 <generatePublisherEvidence enabled="false"/>
9 </runtime>
10 <appSettings>
11 <!--
12 ; 0 - No output
13 ; 1 - Debugger (Such as DbgView)
14 ; 2 - File (Overwrite the old file and doesn't close it until application exits)
15 ; 3 - File (Append the log at the end of file and close it after each log output)
16 ; 4 - Debugger&File (Append the log at the end of file and close it after each log output)
17 -->
18 <add key="logDestination" value="4"/>
19 <!--log file path. if value is null or string.empty, don't ouput log to file-->
20 <!--example:%LocalAppData%\log.txt-->
21 <add key="logPath" value="%LocalAppData%\log.txt"/>
22 </appSettings>
23 </configuration>
logDestination
  • 0         沒有任何日志輸出
  • 1         可以輸出到DebugView
  • 2         每次啟動應用程序后,把上次寫的日志清除掉,重新寫一份日志
  • 3         第一次啟動應用程序后,創建日志文件,后面一直累加

logPath 文本日志的文件位置, 推薦使用 AppData里面的路徑,這個是系統默認的應用程序 數據存儲路徑。

如果搞別的,也可以,但是要考慮只讀、權限等問題,由於客戶機環境復雜,所以還是放在AppData 比較省心。

 

 使用方法

在需要打印日志的地方調用方法, 大致分為:簡單打印、打印變量、打印方法執行結果、打印堆棧信息、打印異常。

下面只列舉了一部分,

 1 // UI|2011/12/20 14:57:39 630 | Test Write Method 
2 LogHelper.Write("Test Write Method");
3
4 bool? testBool = false;
5 /// UI|2011/12/20 14:57:48 277 | False
6 LogHelper.Write(testBool);
7
8 Double testDouble = 0.2256;
9 /// UI|2011/12/20 14:57:48 279 | 0.2256
10 LogHelper.Write(testDouble);
11
12 /// UI|2011/12/20 15:01:28 801 | current ID:115001 Name:Jackon
13 LogHelper.Write("current ID:{0} Name:{1}", 115001, "Jackon");
14
15 bool? ret = DoTestIsOK();
16 /// UI|2011/12/20 15:17:04 732 | Method:DoTestIsOK --> Result:Null
17 LogHelper.WriteMethod("DoTestIsOK", ret);
18 int a = 1, b = 3;
19 int ret = DoTestAdd(a, b);
20
21 /// UI|2011/12/20 15:17:05 316 | Method:DoTestAdd --> Result:4 -- Parms:a:1 b:3
22 LogHelper.WriteMethod("DoTestAdd", ret, "a:{0} b:{1}", a, b);
23


原理

C# 的Trace可以打印到output里面,Realse后,也可以打印到DebugView中。

這里的實現是豐富了Trace的功能,並且將日志輸出為 不同的格式,打印出來后方便分析。

通過     Trace.Listeners 可以控制輸出的目的地。

話不多說,都在代碼里,如下:

  1     #region init
2 /// <summary>
3 /// init by configuration
4 /// </summary>
5 public static void Init()
6 {
7 #region define
8 string logPathKey = "logPath", logDestinationKey = "logDestination", autoFlushKey = "autoFlush";
9 string logPath = string.Empty, logDestination = string.Empty;
10 FileStream stream;
11 FileMode fileMode;
12 #endregion
13
14 #region get destination
15 //no destination,return
16 if (!ConfigurationManager.AppSettings.AllKeys.Contains(logDestinationKey)) return;
17 logDestination = ConfigurationManager.AppSettings[logDestinationKey].Trim();
18
19 int logType = 0;
20 Int32.TryParse(logDestination, out logType);
21 //if logType == 0 , don't record log
22 isLog = (logType != 0);
23 #endregion
24
25
26
27
28
29
30 #region switch log type
31 switch (logType)
32 {
33 case 0:
34 {
35 //0 - No output
36 Trace.Listeners.Clear();
37 return;
38 }
39 case 1:
40 {
41 //1 - Debugger (Such as DbgView)
42 //use default listener
43 return;
44 }
45 case 2:
46 {
47 //2 - File (Overwrite the old file and doesn't close it until application exits)
48 Trace.Listeners.Clear();
49 fileMode = FileMode.Create; break;
50 }
51 case 3:
52 {
53 //3 - File (Append the log at the end of file and close it after each log output)
54 Trace.Listeners.Clear();
55 fileMode = FileMode.Append; break;
56 }
57 case 4:
58 {
59 //4 - Debugger&File (Append the log at the end of file and close it after each log output)
60 fileMode = FileMode.Append; break;
61 }
62
63 default: return;
64 }
65 #endregion
66
67 #region check path
68 //path is null
69 logPath = ConfigurationManager.AppSettings[logPathKey].Trim();
70 if (string.IsNullOrEmpty(logPath)) return;
71
72 //path has invalid char
73 var pathCharArray = logPath.ToCharArray();
74 if (pathCharArray.Any(o => Path.GetInvalidPathChars().Contains(o)))
75 return;
76
77 //FileName has invalid char
78 //note : invalid file name chars count is 41,
79 //invalid path chars count is 36
80 //and , the top 36 of invalid file name chars are same as invalid path chars
81 //so,first check path invalid chars,second check filename,only filename
82 var filenameCharArray = Path.GetFileName(logPath).ToCharArray();
83 if (filenameCharArray.Any(o => Path.GetInvalidFileNameChars().Contains(o)))
84 return;
85
86 //EnvironmentVariables Path
87 if (logPath.Contains('%'))
88 logPath = Environment.ExpandEnvironmentVariables(logPath);
89
90 //cheng relative path to absolute path.
91 if (String.IsNullOrEmpty(Path.GetPathRoot(logPath)))
92 logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, logPath);
93 #endregion
94
95 #region file log
96 //risk:directory readonly;need administrator right to createfile;and so on
97 //use try-catch
98 try
99 {
100 if (!Directory.Exists(Path.GetDirectoryName(logPath)))
101 Directory.CreateDirectory(Path.GetDirectoryName(logPath));
102
103 stream = File.Open(logPath, fileMode, FileAccess.Write, FileShare.ReadWrite);
104 TextWriterTraceListener text = new TextWriterTraceListener(stream);
105 //text.TraceOutputOptions = TraceOptions.DateTime;
106 Trace.Listeners.Add(text);
107 }
108 catch (Exception ex)
109 {
110 Trace.Write(ex);
111 }
112 #endregion
113
114 }
115 #endregion


結束,歡迎拍磚。

代碼下載




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM