using System; using System.Diagnostics; using System.Text; using System.IO; using System.Threading; namespace Common { public class LogEngine { private LogSetting m_Setting; public LogEngine() { m_Setting = new LogSetting(); } public LogEngine(string name) : this() { m_Setting.Name = name; } private void WriteWords(object words) { // Lock file when the file has be writting at anthoer thread. lock (_WriterLock) { StreamWriter stream = null; try { string dir = GetCurrentDirectoryPath(); string filename = GetFileNameWithPartMark(); string fullpath = Path.Combine(dir, filename); FileInfo fileInf; if (Directory.Exists(dir) == false) { Directory.CreateDirectory(dir); } for (int part = 1; true; part++) { fileInf = new FileInfo(string.Format(fullpath, part)); if (fileInf.Exists) { if (fileInf.Length < Setting.MaxSizeByte) { stream = fileInf.AppendText(); break; } } else { stream = fileInf.CreateText(); break; } } stream.Write(words); } catch (Exception ex) { using (var sw = File.CreateText( AppDomain.CurrentDomain.BaseDirectory + "LogEngine." + DateTime.Now.ToString("yyyyMMddHHmmssfff.") + new Random().Next(9999) + ".log")) { sw.WriteLine("Exception when write words: {0}", words); sw.WriteLine("Exception Message: {0}", ex.Message); sw.WriteLine("Exception StackTrace: {0}", ex.StackTrace); } } finally { if (stream != null) { stream.Dispose(); } } } } public void Write(string words) { if (this.m_Setting.BackgroundThread) { Thread t = new Thread(new ParameterizedThreadStart(WriteWords)); t.IsBackground = true; t.Start(words); } else { WriteWords(words); } } public string Write(string format, params object[] objs) { string words = string.Format(format, objs); Write(words); return words; } public string WriteLine(string format, params object[] objs) { StringBuilder sbWords = new StringBuilder(); sbWords.AppendFormat(format, objs).AppendLine(); string words = sbWords.ToString(); Write(words); return words; } public string WriteLineWithDataTime(string format, params object[] objs) { StringBuilder sbWords = new StringBuilder(); sbWords.Append(DateTime.Now.ToString(Setting.DateTimeFormat)); sbWords.AppendFormat(format, objs); sbWords.AppendLine(); string words = sbWords.ToString(); Write(words); return words; } public LogSetting Setting { get { return m_Setting; } } public string GetCurrentDirectoryPath() { string dir = Setting.Home; if (Setting.FoldersTree != null) { foreach (var flag in Setting.FoldersTree) { switch (flag) { case FolderFlag.Name: dir = Path.Combine(dir, Setting.Name); break; case FolderFlag.Date: dir = Path.Combine(dir, DateTime.Now.ToString(LogSetting.DATE_FORMAT)); break; } } } return dir; } private string GetFileNameWithPartMark() { return string.Format(_LOG_FILENAME_FMT, _LOG_FILENAME_SEPARATOR, Setting.Name, DateTime.Now.ToString(Setting.PartOfFileNameDHFormat), _PART_MARK).Trim(_LOG_FILENAME_SEPARATOR); } public void ExploreFolder() { Process.Start("explorer.exe", GetValidFolderPath(GetCurrentDirectoryPath())); } private string GetValidFolderPath(string path) { if (string.IsNullOrEmpty(path)) path = AppDomain.CurrentDomain.BaseDirectory; if (Directory.Exists(path) == false) path = GetValidFolderPath(Path.GetDirectoryName(path)); return path; } // Lock the file variable, must define static private static readonly object _WriterLock = new object(); // {0} Name; {1} DateTime; {2} Part const string _LOG_FILENAME_FMT = "{1}{0}{2}{0}P{3}.log"; const string _PART_MARK = "{0}"; const char _LOG_FILENAME_SEPARATOR = '_'; public static void CleanUpOutdated(string dirPath, uint days, string pattern = "*.log") { try { if (Directory.Exists(dirPath)) { DirectoryInfo dInfo; foreach (var dPath in Directory.GetDirectories(dirPath)) { try { dInfo = new DirectoryInfo(dPath); foreach (var fInfo in dInfo.GetFiles(pattern, SearchOption.AllDirectories)) { try { if (DateTime.Now.Subtract(fInfo.LastWriteTime).Days > days) fInfo.Delete(); } catch { } } if (dInfo.GetFiles("*", SearchOption.AllDirectories).Length < 1) { dInfo.Delete(); } } catch { } } } } catch { } } public class LogSetting { string _name; string _home; FolderFlag[] _foldersTree; internal long MaxSizeByte; internal string PartOfFileNameDHFormat; uint _maxSize; bool _byHour; public LogSetting() { _name = string.Empty; _home = "Log"; MaxSize = 5; //BackgroundThread = true; ByHour = false; DateTimeFormat = "HH:mm:ss.fff: "; SetFoldersTree(FolderFlag.Date); } public string Name { get { return _name; } set { if (value.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) throw new ArgumentException("Contains invalid characters", "value"); _name = value; } } public string Home { get { return _home; } set { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("value"); if (value.IndexOfAny(Path.GetInvalidPathChars()) >= 0) throw new ArgumentException("Contains invalid characters", "value"); _home = value; } } public uint MaxSize { get { return _maxSize; } set { if (value > 0 && value <= 100) { _maxSize = value; MaxSizeByte = _maxSize * 1048576; // 1MB = 1048576 byte } } } public bool ByHour { get { return _byHour; } set { PartOfFileNameDHFormat = value ? "yyyyMMdd_HH" : DATE_FORMAT; _byHour = value; } } public string DateTimeFormat { get; set; } public FolderFlag[] FoldersTree { get { return _foldersTree.Clone() as FolderFlag[]; } } public void SetFoldersTree(params FolderFlag[] folders) { _foldersTree = folders; } public bool BackgroundThread { get; set; } internal const string DATE_FORMAT = "yyyyMMdd"; } public enum FolderFlag { Name, Date } } }