需求:程序啓動後到關閉,只新建一個Log文件,所有的Log內容都在一個文件中。
注意:爲了避免Log內容錯亂,使用Dispatcher調度
Log
Log.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Log
{
public delegate string BuildMessage();
public class Log
{
private static string DLL_PATH = "DebugLog.dll";
private static string OUTPUT_PATH = "";
private static ILog _iLog = null;
private static bool _isNeedLog = false;
static Log()
{
try
{
if (InitConfigSettings())
{
var type = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + DLL_PATH).GetTypes()?.Single((T) => T.GetInterface(nameof(ILog)) != null);
object[] parameters = new object[] { OUTPUT_PATH };
_iLog = (ILog)Activator.CreateInstance(type, parameters);
}
}
catch
{
}
}
public static void Write(string message)
{
if (_iLog != null)
{
try
{
if(FilterLog())
{
_iLog.Write(message);
}
}
catch(Exception ex)
{
_iLog.Write(ex.StackTrace.ToString());
}
}
}
public static void Wirte(BuildMessage messageAction)
{
if (_iLog != null)
{
try
{
if (FilterLog())
{
_iLog.Write(messageAction);
}
}
catch (Exception ex)
{
_iLog.Write(ex.StackTrace.ToString());
}
}
}
private static bool InitConfigSettings()
{
// get app config file
string dllPath = string.Format("{0}{1}", AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory, DLL_PATH);
var appconfig = ConfigurationManager.OpenExeConfiguration(dllPath);
OUTPUT_PATH = appconfig.AppSettings.Settings["OutPutPath"].Value;
var _isNeedLog = appconfig.AppSettings.Settings["LogIsNeed"].Value;
if (_isNeedLog == null || !_isNeedLog.Equals(Boolean.TrueString, StringComparison.OrdinalIgnoreCase))
{
return false;
}
return true;
}
private static bool FilterLog()
{
return _isNeedLog == false ? true : false;
}
}
}
ILog.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Log
{
public interface ILog
{
void Write(string meaasge);
void Write(BuildMessage messageAction);
void Dispose();
}
}
DebugLog
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
<appSettings>
<add key="LogIsNeed" value="true"/>
<add key="OutPutPath" value=""/>
</appSettings>
</configuration>
DebugLogWrite .cs
using Log;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace DebugLog
{
public class DebugLogWrite : ILog, IDisposable
{
private string _outPutPath;
private bool _isDispose;
private object _locker = new object();
private FileStream _fileStream = null;
private StreamWriter _streamWriter = null;
private Thread _workingThread = null;
private Dispatcher _workingDispatcher = null;
private ManualResetEvent _dispatcherReadSingle = new ManualResetEvent(false);
private DispatcherOperation _dispatcherOperation = null;
private string FILE_NAME = "log";
public DebugLogWrite(string outPutPath)
{
try
{
var fullPath = Path.GetFullPath(outPutPath);
if (!Directory.Exists(fullPath))
{
Directory.CreateDirectory(fullPath);
var searchPattern = string.Format("log", DateTime.Today.ToString("yyyyMMdd"));
var fileList = Directory.GetFiles(fullPath, searchPattern, SearchOption.TopDirectoryOnly)
.Where(p => CheckIsNumber(p)).OrderBy(p => new FileInfo(p).Name);
var fileNumber = "000";
if (fileList.Count() > 0)
{
FileInfo maxFileInfo = new FileInfo(fileList.Last());
fileNumber = maxFileInfo.Name.Substring(4, 3);
if (fileNumber != "999")
{
fileNumber = (Convert.ToInt32(fileNumber) + 1).ToString().PadLeft(3, '0');
}
}
var fileName = string.Format(FILE_NAME, DateTime.Today.ToString("yyyyMMdd"), fileNumber);
_outPutPath = Path.Combine(fullPath, fileName);
_fileStream = new FileStream(_outPutPath, FileMode.Create, FileAccess.Write);
_streamWriter = new StreamWriter(_fileStream, Encoding.UTF8);
_workingThread = new Thread(() =>
{
_workingDispatcher = Dispatcher.CurrentDispatcher;
_dispatcherReadSingle.Set();
Dispatcher.Run();
});
_workingThread.Start();
_dispatcherReadSingle.WaitOne();
}
}
catch
{
}
}
public void Dispose()
{
if (!_isDispose)
{
_isDispose = true;
Dispose(true);
}
}
protected virtual void Dispose(bool disposing)
{
try
{
if (disposing)
{
var task = _dispatcherOperation.Task.ContinueWith((p) =>
{
_dispatcherReadSingle?.Dispose();
_dispatcherOperation?.Abort();
_workingDispatcher?.InvokeShutdown();
});
}
}
catch
{
_dispatcherReadSingle?.Dispose();
_dispatcherOperation?.Abort();
_workingDispatcher?.InvokeShutdown();
_streamWriter?.Close();
_fileStream?.Close();
}
}
public void Write(string meaasge)
{
if (!_isDispose)
{
var threadId = Thread.CurrentThread.ManagedThreadId;
lock (_locker)
{
_dispatcherOperation = _workingDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate ()
{
try
{
var log = new StringBuilder();
log.AppendLine();
log.Append(DateTime.Now).Append(meaasge);
}
catch
{
_streamWriter?.Close();
_fileStream?.Close();
}
}));
}
}
}
public void Write(BuildMessage messageAction)
{
if (!_isDispose)
{
Write(messageAction?.Invoke());
}
}
private bool CheckIsNumber(string file)
{
try
{
var number = new FileInfo(file).Name.Substring(4, 3);
int result = 0;
if (int.TryParse(number, out result))
{
return true;
}
return false;
}
catch
{
return false;
}
}
}
}