輔助紀錄的 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;
}
}
}
}
留言
張貼留言