輔助紀錄的 API - LogAPI
這個是我撰寫的 API ,透過這個 API ,將系統的錯誤訊息全存到指定的 log
並且會排出版面來顯示錯誤資訊
由於打算放到共用類別庫,所以所有的參考都僅參考 .Net Framework 內已定義的類別庫 並透過 StackTrace 及 StackFrame 取得發生例外的函式名稱!
並且會排出版面來顯示錯誤資訊
由於打算放到共用類別庫,所以所有的參考都僅參考 .Net Framework 內已定義的類別庫 並透過 StackTrace 及 StackFrame 取得發生例外的函式名稱!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Mail; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using Microsoft.Win32.SafeHandles; namespace WCT.Common { public class LogAPI : IDisposable { private struct BY_HANDLE_FILE_INFORMATION { public UInt32 FileAttributes; public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime; public UInt32 VolumeSerialNumber; public UInt32 FileSizeHigh; public UInt32 FileSizeLow; public UInt32 NumberOfLinks; public UInt32 FileIndexHigh; public UInt32 FileIndexLow; } [DllImport("kernel32.dll")] private static extern bool AllocConsole(); [DllImport("kernel32.dll")] private static extern bool AttachConsole(UInt32 dwProcessId); [DllImport("kernel32.dll")] private static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, SafeFileHandle hSourceHandle, IntPtr hTargetProcessHandle, out SafeFileHandle lpTargetHandle, UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwOptions); [DllImport("kernel32.dll")] private static extern bool FreeConsole(); [DllImport("kernel32.dll")] private static extern bool GetFileInformationByHandle(SafeFileHandle hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation); [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("kernel32.dll")] private static extern SafeFileHandle GetStdHandle(UInt32 nStdHandle); [DllImport("user32.dll", SetLastError = true)] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out UInt32 lpdwProcessId); [DllImport("kernel32.dll")] private static extern bool SetStdHandle(UInt32 nStdHandle, SafeFileHandle hHandle); private const UInt32 ATTACH_PARENT_PROCESS = 0xFFFFFFFF; private const UInt32 STD_INPUT_HANDLE = 0xFFFFFFF6; private const UInt32 STD_OUTPUT_HANDLE = 0xFFFFFFF5; private const UInt32 STD_ERROR_HANDLE = 0xFFFFFFF4; private const UInt32 DUPLICATE_SAME_ACCESS = 2; private static LogAPI mInstance = null; private static string mDirectory; private System.DateTime mDate; private string mFileName; private string mEntryFileName; private System.DateTime mStartTime; private System.Diagnostics.Stopwatch mStopWatch; private int ErrorCount; private int ReConnectionErrorCount; private StringBuilder ProgramInfo = new StringBuilder(); private StringBuilder LogMessage = new StringBuilder(); private StringBuilder ErrorMessage = new StringBuilder(); private StringBuilder EntryMessage = new StringBuilder(); private bool m_isSend = false; private bool m_isCmd = false; private string mFuncName = "TestLogAPI"; private LogAPI() { mDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Log\\"); mStartTime = DateTime.Now; mStopWatch = new System.Diagnostics.Stopwatch(); mStopWatch.Start(); ErrorCount = 0; ReConnectionErrorCount = 0; if (!Directory.Exists(mDirectory)) { Directory.CreateDirectory(mDirectory); } else { // 清理超過一個月的 Log 紀錄檔 try { DirectoryInfo dirInfo = new DirectoryInfo(mDirectory); DateTime today = DateTime.Today; foreach (FileInfo FInfo in dirInfo.GetFiles("*.log")) { // 檔案保留 30 天 if (today.Subtract(FInfo.CreationTime) > new TimeSpan(30, 0, 0, 0)) { FInfo.Delete(); } } } catch { } } //IntPtr ptr = GetForegroundWindow(); //UInt32 processId; //GetWindowThreadProcessId(ptr, out processId); //Process process = Process.GetProcessById(Convert.ToInt32(processId)); //if (process.ProcessName == "cmd" || process.ProcessName == "command") // m_isCmd = true; if (Console.Out != null) m_isCmd = true; ProgramInfo.AppendLine(string.Format("Assembly FullName: {0}", Assembly.GetEntryAssembly().FullName)); ProgramInfo.AppendLine(string.Format("Assembly CodeBase: {0}", Assembly.GetEntryAssembly().CodeBase)); ProgramInfo.AppendLine(string.Format("Assembly Location: {0}", Assembly.GetEntryAssembly().Location)); ProgramInfo.AppendLine(string.Format("Computer Name : {0}", Environment.MachineName)); ProgramInfo.Append(getEntryPointAndCommandArgsInfo); ProgramInfo.AppendLine(string.Format("Run as : {0}", System.Security.Principal.WindowsIdentity.GetCurrent().Name)); ProgramInfo.AppendLine(string.Format("Run Time : {0:yyyy/MM/dd HH:mm:ss.fff}", System.DateTime.Now)); } public static LogAPI GetInstance() { if (mInstance == null) { mInstance = new LogAPI(); mInstance.mDate = System.DateTime.Today; mInstance.mFileName = string.Format("{0:yyyyMMdd}.log", mInstance.mDate); mInstance.mEntryFileName = string.Format("{0:yyyyMMdd}_Entry.log", mInstance.mDate); } else { if (mInstance.mDate != System.DateTime.Today) { mInstance.mDate = System.DateTime.Today; mInstance.mFileName = string.Format("{0:yyyyMMdd}.log", mInstance.mDate); } } return mInstance; } public void SetSMTP(string SMTP, string SMTPID, string SMTPPW, string SMTPSender, string SMTPSenderName) { this.isSend = true; this.SMTP = SMTP; this.SMTPID = SMTPID; this.SMTPPW = SMTPPW; this.SMTPSender = SMTPSender; this.SMTPSenderName = SMTPSenderName; } public void SetSMTPEnabled() { this.isSend = true; } public void SetSMTPDisabled() { this.isSend = false; } public bool isSend { get { return m_isSend; } private set { m_isSend = value; } } public string CurrentEnvironment { get; set; } public string SMTP { get; private set; } public string SMTPID { get; private set; } public string SMTPPW { get; private set; } public string SMTPSender { get; private set; } public string SMTPSenderName { get; private set; } public string FuncName { get { return mFuncName; } set { mFuncName = value; } } public void TakeEntryMethod(params object[] value) { System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); System.Diagnostics.StackFrame frame = trace.GetFrame(1); var parameters = frame.GetMethod().GetParameters(); bool pflag = true; StringBuilder _sb = new StringBuilder(); StringBuilder goalsb; #if DEBUG goalsb = EntryMessage; #else goalsb = LogMessage; #endif lock (goalsb) { _sb.Append(string.Format("[Entry][{0:HH:mm:ss.fff}][", System.DateTime.Now)); MethodInfo mi = frame.GetMethod() as MethodInfo; if (mi != null) _sb.Append(string.Format("{0} {1}.{2}(", mi.ReturnType.FullName, mi.ReflectedType.FullName, mi.Name)); else _sb.Append(string.Format("{0}.{1}(", frame.GetMethod().ReflectedType.FullName, frame.GetMethod().Name)); for (int i = 0; i < parameters.Length; i++) { if (pflag) pflag = false; else _sb.Append(","); if (i < value.Length) { _sb.Append(string.Format("{0}=", parameters[i].ToString())); if (value[i] == null) _sb.Append("NULL"); else if (value[i].Equals(DBNull.Value)) _sb.Append("DBNull"); else if (value[i] is DateTime) { if (((DateTime)value[i]).ToString("HHmmssfff") == "000000000") _sb.AppendFormat("{0:yyyy/MM/dd}", value[i]); else _sb.AppendFormat("{0:yyyy/MM/dd HH:mm:ss.fff}", value[i]); } else _sb.Append(value[i].ToString()); } else _sb.Append(string.Format("{0}", parameters[i].ToString())); } _sb.AppendLine(")]"); if (m_isCmd) Console.Write(_sb.ToString()); goalsb.Append(_sb.ToString()); } } public void InfoMsg(string msg) { InfoMsg(msg, false); } public void InfoMsg(string format, params object[] args) { InfoMsg(string.Format(format, args)); } public void InfoMsg(string msg, bool showStackFrame) { if (showStackFrame) { string currentMethod = System.Reflection.MethodBase.GetCurrentMethod().Name; System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); System.Diagnostics.StackFrame frame = trace.GetFrame(1); var parameters = frame.GetMethod().GetParameters(); bool pflag = true; StringBuilder sb = new StringBuilder(); lock (LogMessage) { sb.Append(string.Format("[Info.][{0:HH:mm:ss.fff}][{1}+{2}(", System.DateTime.Now, frame.GetMethod().ReflectedType.FullName, frame.GetMethod().Name)); foreach (var para in parameters) { if (pflag) pflag = false; else sb.Append(","); sb.Append(para.ToString()); } sb.AppendLine(string.Format(")]{0}", msg)); Console.WriteLine(sb.ToString()); LogMessage.Append(sb.ToString()); } } else { lock (LogMessage) { string AppendMsg = string.Format("[Info.][{0:HH:mm:ss.fff}]{1}", System.DateTime.Now, msg); LogMessage.AppendLine(AppendMsg); Console.WriteLine(AppendMsg); } } } public void ErrorMsg(string msg, Exception ex) { if (ex == null) { return; } System.DateTime LogTime = System.DateTime.Now; lock (LogMessage) { StringBuilder sbLogMessage = new StringBuilder(); StringBuilder sbErrorMessage = new StringBuilder(); ErrorCount += 1; var sex = ex as System.Data.SqlClient.SqlException; if (sex != null && sex.ErrorCode == -2146232060) ReConnectionErrorCount += 1; sbLogMessage.AppendLine(string.Format("[Error][{0:HH:mm:ss.fff}][{2:00}]{1}", LogTime, msg, ErrorCount)); sbErrorMessage.AppendLine(string.Format("DetailID = {0}", ErrorCount)); sbErrorMessage.AppendLine(string.Format("\tType: {0}", ex.GetType().FullName)); var w32ex = ex as System.ComponentModel.Win32Exception; if (w32ex != null) { sbErrorMessage.AppendLine(string.Format("\tErr. Code:{0}", w32ex.ErrorCode)); } sbErrorMessage.AppendLine(string.Format("\tMessage: {0}", ex.Message)); if (!string.IsNullOrEmpty(ex.StackTrace)) { sbErrorMessage.AppendLine("\tStack:"); bool flag = true; foreach (string s in ex.StackTrace.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)) { sbErrorMessage.Append("\t\t"); if (flag) flag = false; else sbErrorMessage.Append(" "); sbErrorMessage.AppendLine(s); } } Console.Write(sbLogMessage.ToString()); Console.Write(sbErrorMessage.ToString()); LogMessage.Append(sbLogMessage.ToString()); ErrorMessage.Append(sbErrorMessage.ToString()); } } public string getEntryPointAndCommandArgsInfo { get { StringBuilder sb = new StringBuilder(); sb.Append(string.Format("Assembly EntryPoint: {0}+{2} {1}(", Assembly.GetEntryAssembly().EntryPoint.DeclaringType, Assembly.GetEntryAssembly().EntryPoint.Name, Assembly.GetEntryAssembly().EntryPoint.ReturnType)); int pCount = 0; foreach (var p in Assembly.GetEntryAssembly().EntryPoint.GetParameters()) { if (pCount > 0) { sb.Append(","); } sb.Append(p.ToString()); pCount += 1; } sb.AppendLine(")"); if (System.Environment.GetCommandLineArgs().Length > 1) { sb.AppendLine("CommandLine Args :"); pCount = 0; foreach (string arg in System.Environment.GetCommandLineArgs()) { sb.AppendLine(string.Format("\t{0,2}=>\t{1}", pCount, arg)); pCount += 1; } } return sb.ToString(); } } public string getFileDetails() { return getFileDetails(false); } public string getFileDetails(bool FileExists) { StringBuilder sb = new StringBuilder(); if (FileExists) { sb.AppendLine(""); sb.AppendLine("======================="); sb.AppendLine(string.Format("Log Start Time: {0:yyyy/MM/dd HH:mm:ss.fff}", mStartTime)); sb.Append(getEntryPointAndCommandArgsInfo); sb.AppendLine(string.Format("Current Environment: {0}", CurrentEnvironment)); sb.AppendLine("======================="); } else { sb.AppendLine("***********************"); sb.AppendLine("* FILE DETAILS *"); sb.AppendLine("***********************"); sb.Append(ProgramInfo.ToString()); sb.AppendLine(string.Format("Current Environment: {0}", CurrentEnvironment)); } return sb.ToString(); } public string getLogMessageDetails { get { if (LogMessage.Length > 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine("***********************"); sb.AppendLine("* LOG MESSAGE DETAILS *"); sb.AppendLine("***********************"); sb.Append(LogMessage.ToString()); return sb.ToString(); } else { return ""; } } } public string getEntryMessageDetails { get { if (LogMessage.Length > 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine("***********************"); sb.AppendLine("* ENTRY MSG. DETAILS *"); sb.AppendLine("***********************"); sb.Append(EntryMessage.ToString()); return sb.ToString(); } else { return ""; } } } public string getExceptionDetails { get { if (ErrorMessage.Length > 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine("***********************"); sb.AppendLine("* EXCEPTION DETAILS *"); sb.AppendLine("***********************"); sb.Append(ErrorMessage.ToString()); return sb.ToString(); } else { return ""; } } } public string getFooter(DateTime current, double runSeconds) { StringBuilder sb = new StringBuilder(); sb.AppendLine("***********************"); sb.AppendLine(string.Format("Log Write Time: {0:yyyy/MM/dd HH:mm:ss.fff}", current)); sb.AppendLine(string.Format("本次執行花費時間: {0} 秒", runSeconds)); sb.AppendLine("***********************"); return sb.ToString(); } public void SaveLog() { try { mStopWatch.Stop(); bool logExists = File.Exists(Path.Combine(mDirectory, mFileName)); bool logEntryExists = File.Exists(Path.Combine(mDirectory, mEntryFileName)); DateTime currentdt = DateTime.Now; using (FileStream fs = File.Open(Path.Combine(mDirectory, mFileName), FileMode.Append)) { using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default)) { sw.Write(getFileDetails(logExists)); sw.Write(getLogMessageDetails); sw.Write(getExceptionDetails); sw.Write(getFooter(currentdt, mStopWatch.Elapsed.TotalSeconds)); sw.Close(); } fs.Close(); } if (EntryMessage.Length >= 0) { using (FileStream fs = File.Open(Path.Combine(mDirectory, mEntryFileName), FileMode.Append)) { using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default)) { sw.Write(getFileDetails(logEntryExists)); sw.Write(getEntryMessageDetails); sw.Write(getFooter(currentdt, mStopWatch.Elapsed.TotalSeconds)); sw.Close(); } fs.Close(); } } } catch (Exception ex) { throw ex; } } ~LogAPI() { Dispose(); } public new void Dispose() { try { SaveLog(); try { if (isSend && ErrorCount - ReConnectionErrorCount > 0) { SmtpClient smtp = new SmtpClient(); smtp.Host = SMTP; smtp.Credentials = new System.Net.NetworkCredential(SMTPID, SMTPPW); StringBuilder sb = new StringBuilder(); sb.Append(getFileDetails(false)); sb.Append(getLogMessageDetails); sb.Append(getExceptionDetails); sb.AppendLine("***********************"); sb.AppendLine(string.Format("Log Write Time: {0:yyyy/MM/dd HH:mm:ss.fff}", System.DateTime.Now)); sb.AppendLine(string.Format("本次執行花費時間: {0} 秒", mStopWatch.Elapsed.TotalSeconds)); sb.AppendLine("***********************"); MailMessage msg = new MailMessage(); msg.From = new MailAddress(SMTPSender, SMTPSenderName); msg.To.Add(new MailAddress("n960477@mail.hosp.ncku.edu.tw")); msg.Subject = string.Format("{0} 執行結果", mFuncName); msg.Body = sb.ToString(); smtp.Send(msg); } } catch { } ProgramInfo.Remove(0, ProgramInfo.Length); LogMessage.Remove(0, LogMessage.Length); EntryMessage.Remove(0, EntryMessage.Length); ErrorMessage.Remove(0, ErrorMessage.Length); ErrorCount = ReConnectionErrorCount = 0; GC.SuppressFinalize(this); } catch (Exception ex) { throw ex; } } } }
留言
張貼留言