초기 커밋.
This commit is contained in:
139
JWH/EXTENSIONS/ExtensionAPI.cs
Normal file
139
JWH/EXTENSIONS/ExtensionAPI.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace JWH
|
||||
{
|
||||
|
||||
public static class ExtensionAPI
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 네트워크 리소스
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct NETRESOURCE
|
||||
{
|
||||
public uint dwScope;
|
||||
public uint dwType;
|
||||
public uint dwDisplayType;
|
||||
public uint dwUsage;
|
||||
public string lpLocalName;
|
||||
public string lpRemoteName;
|
||||
public string lpComment;
|
||||
public string lpProvider;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set Tab stops to a width of 4
|
||||
/// </summary>
|
||||
private const int EM_SETTABSTOPS = 0x00CB;
|
||||
|
||||
/// <summary>
|
||||
/// 네트워크 드라이브 연결
|
||||
/// </summary>
|
||||
/// <param name="hwndOwner"></param>
|
||||
/// <param name="lpNetResource"></param>
|
||||
/// <param name="lpPassword"></param>
|
||||
/// <param name="lpUserID"></param>
|
||||
/// <param name="dwFlags"></param>
|
||||
/// <param name="lpAccessName"></param>
|
||||
/// <param name="lpBufferSize"></param>
|
||||
/// <param name="lpResult"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("mpr.dll", CharSet = CharSet.Auto)]
|
||||
public static extern int WNetUseConnection(
|
||||
IntPtr hwndOwner,
|
||||
[MarshalAs(UnmanagedType.Struct)] ref NETRESOURCE lpNetResource,
|
||||
string lpPassword,
|
||||
string lpUserID,
|
||||
uint dwFlags,
|
||||
StringBuilder lpAccessName,
|
||||
ref int lpBufferSize,
|
||||
out uint lpResult);
|
||||
|
||||
/// <summary>
|
||||
/// 네트워크 드라이브 해제
|
||||
/// </summary>
|
||||
/// <param name="lpName"></param>
|
||||
/// <param name="dwFlags"></param>
|
||||
/// <param name="fForce"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("mpr.dll", EntryPoint = "WNetCancelConnection2", CharSet = CharSet.Auto)]
|
||||
public static extern int WNetCancelConnection2A(string lpName, int dwFlags, int fForce);
|
||||
|
||||
/// <summary>
|
||||
/// 네트워크 드라이브 연결
|
||||
/// </summary>
|
||||
/// <param name="server"></param>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="pwd"></param>
|
||||
/// <returns></returns>
|
||||
public static int ConnectRemoteServer(string server, string uid, string pwd)
|
||||
{
|
||||
int capacity = 64;
|
||||
uint resultFlags = 0;
|
||||
uint flags = 0;
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder(capacity);
|
||||
NETRESOURCE ns = new NETRESOURCE();
|
||||
ns.dwType = 1; // 공유 디스크
|
||||
ns.lpLocalName = null; // 로컬 드라이브 지정하지 않음
|
||||
ns.lpRemoteName = $@"\\{server}";
|
||||
ns.lpProvider = null;
|
||||
int result = 0;
|
||||
|
||||
result = WNetUseConnection(IntPtr.Zero, ref ns, pwd, uid, flags, sb, ref capacity, out resultFlags);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 네트워크 드라이브 해제
|
||||
/// </summary>
|
||||
/// <param name="server"></param>
|
||||
/// <returns></returns>
|
||||
public static int CencelRemoteServer(string server)
|
||||
{
|
||||
string lpRemoteName = $@"\\{server}";
|
||||
int result = 0;
|
||||
|
||||
result = WNetCancelConnection2A(lpRemoteName, 1, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SendMessage
|
||||
/// </summary>
|
||||
/// <param name="h"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="wParam"></param>
|
||||
/// <param name="lParam"></param>
|
||||
/// <returns></returns>
|
||||
[DllImport("User32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr SendMessage(IntPtr h, int msg, int wParam, int[] lParam);
|
||||
|
||||
/// <summary>
|
||||
/// 텍스트박스의 탭 간격을 설정합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="tabWidths">탭간격</param>
|
||||
public static void SetTabWidth(this TextBox sender, params int[] tabWidths)
|
||||
{
|
||||
Graphics graphics = sender.CreateGraphics();
|
||||
int characterWidth = 4;
|
||||
//characterWidth = (int)graphics.MeasureString("A", sender.Font).Width;
|
||||
|
||||
int[] lParams = new int[tabWidths.Length];
|
||||
for(int i=0; i< tabWidths.Length; i++)
|
||||
{
|
||||
lParams[i] = tabWidths[i] * characterWidth;
|
||||
if (i > 0) lParams[i] += lParams[i - 1];
|
||||
}
|
||||
|
||||
IntPtr ptr = SendMessage(sender.Handle, EM_SETTABSTOPS, lParams.Length, lParams);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
531
JWH/EXTENSIONS/ExtensionByte.cs
Normal file
531
JWH/EXTENSIONS/ExtensionByte.cs
Normal file
@@ -0,0 +1,531 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
|
||||
namespace JWH
|
||||
{
|
||||
|
||||
public static class ExtensionByte
|
||||
{
|
||||
|
||||
#region [ Byte ] ------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// 바이트 배열을 복제합니다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="offset"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] Clone(this byte[] sender, int offset = -1, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (offset < 0) offset = 0;
|
||||
if (length < 0) length = sender.Length - offset;
|
||||
if (length > sender.Length - offset) length = sender.Length - offset;
|
||||
|
||||
byte[] value = new byte[length];
|
||||
Buffer.BlockCopy(sender, offset, value, 0, length);
|
||||
|
||||
return value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ String ] ----------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// 문자열을 바이트 배열로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ConvertBytes(this string sender)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Encoding.Default.GetBytes(sender);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 진수형태의 문자열을 바이트 배열로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="fromBase">문자열 값의 기수로서 2, 8, 10 또는 16이어야 합니다.</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ConvertBytes(this string sender, int fromBase)
|
||||
{
|
||||
try
|
||||
{
|
||||
char[] arrContains = "0123456789ABCDEF".Substring(0, fromBase).ToCharArray();
|
||||
|
||||
// 기수에서 허용하지 않는 문자를 필터링
|
||||
StringBuilder sb = new StringBuilder();
|
||||
string value = sender.ToUpper();
|
||||
foreach (char ch in value.ToCharArray())
|
||||
{
|
||||
if (arrContains.Contains(ch) == false) continue;
|
||||
sb.Append(ch);
|
||||
}
|
||||
|
||||
value = sb.ToString();
|
||||
List<byte> bytes = new List<byte>();
|
||||
int step = fromBase > 10 ? 2 : 1;
|
||||
if (fromBase == 2) step = 8;
|
||||
for (int i = 0; i < value.Length; i += step)
|
||||
{
|
||||
if (i + step > value.Length) break;
|
||||
byte byteValue = Convert.ToByte(value.Substring(i, step), fromBase);
|
||||
bytes.Add(byteValue);
|
||||
}
|
||||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 바이트 배열을 문자열로 변환합니다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static string ConvertString(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender == null) return string.Empty;
|
||||
if (length < 0) length = sender.Length;
|
||||
|
||||
return Encoding.Default.GetString(sender, index, length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 바이트 배열을 HEX 문자열로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static string ConvertHexString(this byte[] sender, int lineFeed = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender == null) return string.Empty;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int index = 0;
|
||||
int length = (lineFeed <= 0 ? int.MaxValue : lineFeed);
|
||||
while (true)
|
||||
{
|
||||
if (index + length > sender.Length) length = sender.Length - index;
|
||||
if (length == 0) break;
|
||||
sb.AppendLine(BitConverter.ToString(sender, index, length).Replace("-", " "));
|
||||
index += length;
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HEX 문자열을 Byte[]로 변환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ToByteFromHexString(this string sender)
|
||||
{
|
||||
try
|
||||
{
|
||||
int mod = sender.Length % 2;
|
||||
if (mod != 0) return null;
|
||||
|
||||
byte[] array = new byte[sender.Length / 2];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
array[i] = Convert.ToByte(sender.Substring(i * 2, 2), 16);
|
||||
|
||||
return array;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Int ] -------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// int 값을 바이트 배열로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="length">Byte Length</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ConvertByte(this int sender, int length = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] intByte = BitConverter.GetBytes(sender);
|
||||
if (length < 1) length = intByte.Length;
|
||||
|
||||
byte[] convByte = new byte[length];
|
||||
Array.Copy(intByte, convByte, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(convByte);
|
||||
|
||||
return convByte;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 바이트 배열값을 Int로 변환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static int ConvertInt(this byte[] sender, int startIndex = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender == null) return 0;
|
||||
if (length == -1) length = sender.Length;
|
||||
|
||||
byte[] byteBuff = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
byteBuff[i] = sender[startIndex + i];
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
int value = 0;
|
||||
for (int i = 0; i < length; i++)
|
||||
value |= byteBuff[i] << (i * 8);
|
||||
|
||||
return value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return 0;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 2바이트 배열 값을 short(Int16) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static short ConvertInt16(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[2];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToInt16(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 4바이트 배열 값을 int(Int32) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static int ConvertInt32(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[4];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToInt32(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 8바이트 배열 값을 long(Int64) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static long ConvertInt64(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[8];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToInt64(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 2바이트 배열 값을 ushort(UInt16) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static ushort ConvertUInt16(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[2];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToUInt16(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 4바이트 배열 값을 ulong(UInt32) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static ulong ConvertUInt32(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[4];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToUInt32(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 8바이트 배열 값을 ulong(UInt64) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static ulong ConvertUInt64(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[8];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToUInt64(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 4바이트 배열 값을 float(Single 단정밀도 부동 소수점) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static float ConvertSingle(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[4];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToSingle(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 8바이트 배열 값을 double(배정밀도 부동 소수점) 값으로 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static double ConvertDouble(this byte[] sender, int index = 0, int length = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int destIndex = 0;
|
||||
byte[] byteBuff = new byte[8];
|
||||
|
||||
if (sender == null) return 0;
|
||||
if (length < 1) length = sender.Length;
|
||||
if (length > byteBuff.Length) length = byteBuff.Length;
|
||||
destIndex = byteBuff.Length - length;
|
||||
|
||||
Array.Copy(sender, index, byteBuff, destIndex, length);
|
||||
if (BitConverter.IsLittleEndian) Array.Reverse(byteBuff);
|
||||
|
||||
return BitConverter.ToDouble(byteBuff, 0);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// ToObject
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="array"></param>
|
||||
/// <returns></returns>
|
||||
public static T ToObject<T>(this byte[] array) where T : class, new()
|
||||
{
|
||||
try
|
||||
{
|
||||
T obj = new T();
|
||||
using (MemoryStream stream = new MemoryStream(array))
|
||||
{
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
stream.Position = 0;
|
||||
obj = (T)formatter.Deserialize(stream);
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
33
JWH/EXTENSIONS/ExtensionNetwork.cs
Normal file
33
JWH/EXTENSIONS/ExtensionNetwork.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace JWH
|
||||
{
|
||||
|
||||
public static class ExtensionNetwork
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Get PhysicalAddress (MAC Address)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetPhysicalAddress()
|
||||
{
|
||||
|
||||
List<NetworkInterface> list = new List<NetworkInterface>();
|
||||
foreach(NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
if (nic.OperationalStatus == OperationalStatus.Up)
|
||||
list.Add(nic);
|
||||
}
|
||||
|
||||
return list[0].GetPhysicalAddress().ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
505
JWH/EXTENSIONS/ExtensionReflection.cs
Normal file
505
JWH/EXTENSIONS/ExtensionReflection.cs
Normal file
@@ -0,0 +1,505 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace JWH
|
||||
{
|
||||
|
||||
public static class ExtensionReflection
|
||||
{
|
||||
|
||||
public static bool IsDesignMode = LicenseManager.UsageMode == LicenseUsageMode.Designtime;
|
||||
|
||||
|
||||
#region [ PropertiesCopy ] --------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// 현재객체의 속성값을 대상객체의 속성에 복사합니다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="dest">대상객체</param>
|
||||
public static void PropertiesCopy(this object sender, object dest, bool overwrite = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (PropertyInfo property in sender.GetType().GetProperties())
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo destProp = dest.GetType().GetProperty(property.Name, property.PropertyType);
|
||||
if (destProp == null || property.GetType() != destProp.GetType()) continue;
|
||||
//if (!property.CanWrite) continue;
|
||||
if (!destProp.CanWrite) continue;
|
||||
|
||||
var destValue = destProp.GetValue(dest);
|
||||
if (overwrite == false && destValue != null) continue;
|
||||
|
||||
destProp.SetValue(dest, property.GetValue(sender));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재객체의 속성값을 대상객체의 속성에 복사합니다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="dest">대상객체</param>
|
||||
public static void PropertiesCopy(this DataTable sender, object dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender.Rows.Count < 1) return;
|
||||
|
||||
DataRow row = sender.Rows[0];
|
||||
foreach (DataColumn column in sender.Columns)
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo destProp = dest.GetType().GetProperty(column.ColumnName, column.DataType);
|
||||
if (destProp == null) continue;
|
||||
|
||||
try
|
||||
{
|
||||
var obj = row[column.ColumnName];
|
||||
destProp.SetValue(dest, obj);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Object of type 'System.DBNull' cannot be converted to type 'System.String'.
|
||||
// XLogger.Instance.Warn(ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary<string, object>의 값을 대상객체의 속성에 복사합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="dest"></param>
|
||||
public static void PropertiesCopy(this Dictionary<string, object> sender, object dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (KeyValuePair<string, object> item in sender)
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo destProp = dest.GetType().GetProperty(item.Key);
|
||||
if (destProp == null) continue;
|
||||
if (!destProp.CanWrite) continue;
|
||||
|
||||
var obj = Convert.ChangeType(item.Value, destProp.PropertyType);
|
||||
destProp.SetValue(dest, obj);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// value 값을 현재객체의 속성에 복사합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void PropertySet(this object sender, string name, object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo property = sender.GetType().GetProperty(name);
|
||||
if (property == null)
|
||||
foreach (PropertyInfo item in sender.GetType().GetProperties())
|
||||
if (string.Compare(item.Name, name, true) == 0)
|
||||
{
|
||||
property = item;
|
||||
break;
|
||||
}
|
||||
if (property == null) return;
|
||||
if (property.PropertyType != value.GetType())
|
||||
{
|
||||
try
|
||||
{ value = Convert.ChangeType(value, property.PropertyType); }
|
||||
catch
|
||||
{ return; }
|
||||
}
|
||||
|
||||
property.SetValue(sender, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 객체의 속성값을 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public static string PropertyGet(this object sender, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo property = sender.GetType().GetProperty(name);
|
||||
if (property == null)
|
||||
{
|
||||
foreach (PropertyInfo item in sender.GetType().GetProperties())
|
||||
{
|
||||
if (string.Compare(item.Name, name, true) == 0)
|
||||
{
|
||||
property = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (property == null) return string.Empty;
|
||||
return property.GetValue(sender)?.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 객체의 메소드를 호출합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public static object CallMethod(this object sender, string name, object[] parameters)
|
||||
{
|
||||
MethodInfo method = sender.GetType().GetMethod(name);
|
||||
if (method == null) return false;
|
||||
|
||||
return method.Invoke(sender, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 객체의 속성 정보를 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetPropertiesString(this object sender)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine($"Type is {sender.GetType()}");
|
||||
foreach (PropertyInfo property in sender.GetType().GetProperties())
|
||||
{
|
||||
try
|
||||
{
|
||||
sb.AppendLine($" > {property.Name} = {property.GetValue(sender)}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 객체를 복제합니다.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static T Clone<T>(this T sender) where T : class, new()
|
||||
{
|
||||
T obj = new T();
|
||||
try
|
||||
{
|
||||
sender.PropertiesCopy(obj);
|
||||
return obj;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
#region [ GetStringValue(Enum) ] --------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Will get the string value for a given enums value, this will
|
||||
/// only work if you assign the StringValue attribute to
|
||||
/// the items in your enum.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetStringValue(this Enum value)
|
||||
{
|
||||
// Get the type
|
||||
Type type = value.GetType();
|
||||
|
||||
// Get fieldinfo for this type
|
||||
FieldInfo fieldInfo = type.GetField(value.ToString());
|
||||
|
||||
// Get the stringvalue attributes
|
||||
StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(
|
||||
typeof(StringValueAttribute), false) as StringValueAttribute[];
|
||||
|
||||
// Return the first if there was a match.
|
||||
return attribs.Length > 0 ? attribs[0].StringValue : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This attribute is used to represent a string value
|
||||
/// for a value in an enum.
|
||||
/// </summary>
|
||||
public class StringValueAttribute : Attribute
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Holds the stringvalue for a value in an enum.
|
||||
/// </summary>
|
||||
public string StringValue { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor used to init a StringValue Attribute
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public StringValueAttribute(string value)
|
||||
{
|
||||
this.StringValue = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// GetDescription
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDescription<T>(this T e) where T : IConvertible
|
||||
{
|
||||
if (e is Enum)
|
||||
{
|
||||
Type type = e.GetType();
|
||||
Array values = Enum.GetValues(type);
|
||||
|
||||
foreach (int val in values)
|
||||
{
|
||||
if (val == e.ToInt32(CultureInfo.InvariantCulture))
|
||||
{
|
||||
var memInfo = type.GetMember(type.GetEnumName(val));
|
||||
var descriptionAttribute = memInfo[0]
|
||||
.GetCustomAttributes(typeof(DescriptionAttribute), false)
|
||||
.FirstOrDefault() as DescriptionAttribute;
|
||||
|
||||
if (descriptionAttribute != null)
|
||||
{
|
||||
return descriptionAttribute.Description;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#region [ ToClass() ] -------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Converts a DataTable to a list with generic objects
|
||||
/// dataTable.ToClass<Employee>();
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Generic object</typeparam>
|
||||
/// <param name="dataTable">DataTable</param>
|
||||
/// <returns>List with generic objects</returns>
|
||||
public static T[] ToClass<T>(this DataTable dataTable) where T : class, new()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
foreach (var row in dataTable.AsEnumerable())
|
||||
{
|
||||
T obj = new T();
|
||||
|
||||
foreach (PropertyInfo property in obj.GetType().GetProperties())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dataTable.Columns.Contains(property.Name) == false) continue;
|
||||
if (row[property.Name] is System.DBNull) continue;
|
||||
|
||||
var val = row[property.Name];
|
||||
//if (property.PropertyType == typeof(DateTime) && val.GetType() == typeof(string))
|
||||
// DateTime.TryParse(val.ToString(), out val);
|
||||
|
||||
property.SetValue(obj, Convert.ChangeType(val, property.PropertyType, CultureInfo.CurrentCulture), null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
list.Add(obj);
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
catch { throw; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a object to a list with generic objects
|
||||
/// dataTable.ToClass<Employee>();
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Generic object</typeparam>
|
||||
/// <param name="srcArray">DataTable</param>
|
||||
/// <returns>List with generic objects</returns>
|
||||
public static T[] ToClass<T>(this object[] srcArray) where T : class, new()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
|
||||
foreach (object src in srcArray)
|
||||
{
|
||||
T des = new T();
|
||||
list.Add(des);
|
||||
Type desType = des.GetType();
|
||||
|
||||
Type srcType = src.GetType();
|
||||
foreach (PropertyInfo srcProperty in srcType.GetProperties())
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyInfo desProperty = desType.GetProperty(srcProperty.Name);
|
||||
if (desProperty == null) continue;
|
||||
|
||||
var srcValue = srcProperty.GetValue(src);
|
||||
if (srcProperty.PropertyType != desProperty.PropertyType)
|
||||
{
|
||||
srcValue = Convert.ChangeType(srcValue, desProperty.PropertyType);
|
||||
}
|
||||
|
||||
desProperty.SetValue(des, srcValue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Warn(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return list.ToArray();
|
||||
}
|
||||
catch { throw; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static CultureInfo CultureInfo { get; set; }
|
||||
|
||||
public static string ToTitleCase(this string sender)
|
||||
{
|
||||
if (ExtensionReflection.CultureInfo == null)
|
||||
ExtensionReflection.CultureInfo = CultureInfo.CurrentCulture;
|
||||
|
||||
TextInfo textInfo = CultureInfo.TextInfo;
|
||||
|
||||
return textInfo.ToTitleCase(sender.ToLower());
|
||||
}
|
||||
|
||||
public static Bitmap ControlCapture(this Control control, bool clipboard = true)
|
||||
{
|
||||
if (control == null) throw new ArgumentNullException("control");
|
||||
|
||||
Bitmap bitmap = new Bitmap(control.Width, control.Height);
|
||||
control.DrawToBitmap(bitmap, new Rectangle(new Point(0, 0), control.Size));
|
||||
if (clipboard) Clipboard.SetImage(bitmap);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static Bitmap ControlCapture(this Control control, Rectangle rect, bool clipboard = true)
|
||||
{
|
||||
if (control == null) throw new ArgumentNullException("control");
|
||||
|
||||
Bitmap bitmap = new Bitmap(rect.Width, rect.Height);
|
||||
control.DrawToBitmap(bitmap, rect);
|
||||
if (clipboard) Clipboard.SetImage(bitmap);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 문자열을 열거형으로 반환한다
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static T ToEnum<T>(this string sender, T value)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (T)Enum.Parse(typeof(T), sender, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
603
JWH/EXTENSIONS/ExtensionXml.cs
Normal file
603
JWH/EXTENSIONS/ExtensionXml.cs
Normal file
@@ -0,0 +1,603 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace JWH
|
||||
{
|
||||
|
||||
public static class ExtensionXml
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 이름으로 노드를 검색하여 첫번째 노드를 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="fullScan">하위검색</param>
|
||||
/// <returns></returns>
|
||||
public static XmlNode GetSingleNodeByName(this XmlDocument sender, string name, bool fullScan = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (string.Compare(node.Name, name, true) == 0) return node;
|
||||
}
|
||||
if (fullScan == false) return null;
|
||||
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
XmlNode result = node.GetSingleNodeByName(name);
|
||||
if (result != null) return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이름으로 노드를 검색하여 첫번째 노드를 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="fullScan">하위검색</param>
|
||||
/// <returns></returns>
|
||||
public static XmlNode GetSingleNodeByName(this XmlNode sender, string name, bool fullScan = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (string.Compare(node.Name, name, true) == 0) return node;
|
||||
}
|
||||
if (fullScan == false) return null;
|
||||
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
XmlNode result = node.GetSingleNodeByName(name);
|
||||
if (result != null) return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이름으로 노드를 검색하여 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="fullScan">하위검색</param>
|
||||
/// <returns></returns>
|
||||
public static XmlNode[] GetNodesByName(this XmlDocument sender, string name, bool fullScan = true)
|
||||
{
|
||||
List<XmlNode> nodes = new List<XmlNode>();
|
||||
try
|
||||
{
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (string.Compare(node.Name, name, true) == 0)
|
||||
nodes.Add(node);
|
||||
}
|
||||
if (fullScan == false) return nodes.ToArray();
|
||||
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
nodes.AddRange(node.GetNodesByName(name));
|
||||
}
|
||||
|
||||
return nodes.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이름으로 노드를 검색하여 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="fullScan">하위검색</param>
|
||||
/// <returns></returns>
|
||||
public static XmlNode[] GetNodesByName(this XmlNode sender, string name, bool fullScan = true)
|
||||
{
|
||||
List<XmlNode> nodes = new List<XmlNode>();
|
||||
try
|
||||
{
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (string.Compare(node.Name, name, true) == 0)
|
||||
nodes.Add(node);
|
||||
}
|
||||
if (fullScan == false) return nodes.ToArray();
|
||||
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
nodes.AddRange(node.GetNodesByName(name));
|
||||
}
|
||||
|
||||
return nodes.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 경로를 검색하여 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static XmlNode[] GetNodesByPath(this XmlDocument sender, string path)
|
||||
{
|
||||
List<XmlNode> nodes = new List<XmlNode>();
|
||||
List<XmlNode> childs = new List<XmlNode>();
|
||||
try
|
||||
{
|
||||
string[] names = path.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (string.Compare(node.Name, names[0], true) == 0)
|
||||
{
|
||||
if (names.Length > 1) childs.Add(node);
|
||||
else nodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; i < names.Length; i++)
|
||||
sb.AppendFormat($"/{names[i]}");
|
||||
|
||||
foreach (XmlNode node in childs)
|
||||
{
|
||||
nodes.AddRange(node.GetNodesByPath(sb.ToString()));
|
||||
}
|
||||
|
||||
return nodes.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 경로를 검색하여 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static XmlNode[] GetNodesByPath(this XmlNode sender, string path)
|
||||
{
|
||||
List<XmlNode> nodes = new List<XmlNode>();
|
||||
List<XmlNode> childs = new List<XmlNode>();
|
||||
try
|
||||
{
|
||||
string[] names = path.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (string.Compare(node.Name, names[0], true) == 0)
|
||||
{
|
||||
if (names.Length > 1) childs.Add(node);
|
||||
else nodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; i < names.Length; i++)
|
||||
sb.AppendFormat($"/{names[i]}");
|
||||
|
||||
foreach (XmlNode node in childs)
|
||||
{
|
||||
nodes.AddRange(node.GetNodesByPath(sb.ToString()));
|
||||
}
|
||||
|
||||
return nodes.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 속성이 동일한 노드를 검색하여 반환한다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="ignorsCaseName">Name의 대/소문자 무시</param>
|
||||
/// <param name="ignorsCaseValue">Value의 대/소문자 무시</param>
|
||||
/// <param name="attributes"></param>
|
||||
/// <returns></returns>
|
||||
private static bool CheckAttributes(this XmlNode sender, bool ignorsCaseName = true, bool ignorsCaseValue = false, params KeyValuePair<string, string>[] attributes)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (KeyValuePair<string, string> pair in attributes)
|
||||
{
|
||||
foreach (XmlAttribute attribute in sender.Attributes)
|
||||
{
|
||||
if (string.Compare(pair.Key, attribute.Name, ignorsCaseName) == 0)
|
||||
if (string.Compare(pair.Value, attribute.Value, ignorsCaseValue) == 0) continue;
|
||||
else return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드의 속성을 검색한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="ignorsCaseName">Attribute.Name 대/소문자 무시</param>
|
||||
/// <returns></returns>
|
||||
public static XmlAttribute GetAttribute(this XmlNode sender, string name, bool ignorsCase = true)
|
||||
{
|
||||
if (sender == null || sender.Attributes == null) return null;
|
||||
|
||||
foreach (XmlAttribute attribute in sender.Attributes)
|
||||
{
|
||||
if (string.Compare(attribute.Name, name, ignorsCase) == 0)
|
||||
return attribute;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드의 속성값을 반환한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="ignorsCaseName">Attribute.Name 대/소문자 무시</param>
|
||||
/// <returns></returns>
|
||||
public static string GetAttributeValue(this XmlNode sender, string name, bool ignorsCase = true)
|
||||
{
|
||||
if (sender == null) return null;
|
||||
foreach (XmlAttribute attribute in sender.Attributes)
|
||||
{
|
||||
if (string.Compare(attribute.Name, name, ignorsCase) == 0)
|
||||
return attribute.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드의 속성값을 변경한다
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="ignorsCaseName">Attribute.Name 대/소문자 무시</param>
|
||||
/// <returns></returns>
|
||||
public static string SetAttributeValue(this XmlNode sender, string name, string value, bool ignorsCase = true)
|
||||
{
|
||||
foreach (XmlAttribute attribute in sender.Attributes)
|
||||
{
|
||||
if (string.Compare(attribute.Name, name, ignorsCase) == 0)
|
||||
{
|
||||
attribute.Value = value;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void PropertiesCopyAttribute(this XmlNode sender, object dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (XmlAttribute attribute in sender.Attributes)
|
||||
dest.PropertySet(attribute.Name, attribute.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PropertiesCopy(this XmlNode sender, object dest)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
dest.PropertySet(node.Name, node.InnerText);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetText(this XmlNode sender)
|
||||
{
|
||||
if (sender.ChildNodes.Count <= 0) return string.Empty;
|
||||
|
||||
string rtnValue = null;
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (node.GetType() == typeof(XmlText))
|
||||
rtnValue = node.InnerText;
|
||||
}
|
||||
|
||||
return rtnValue;
|
||||
}
|
||||
|
||||
public static void SetText(this XmlNode sender, string value)
|
||||
{
|
||||
XmlNode nodeText = null;
|
||||
foreach (XmlNode node in sender.ChildNodes)
|
||||
{
|
||||
if (node.GetType() == typeof(XmlText))
|
||||
{
|
||||
nodeText.InnerText = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sender.ChildNodes.Count == 0)
|
||||
{
|
||||
sender.InnerText = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// XmlDocument 내용을 문자열로 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="indent"></param>
|
||||
/// <param name="haeder"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetBeautify(this XmlDocument sender, int indent = 2, bool haeder = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
string rtn = string.Empty;
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings
|
||||
{
|
||||
Encoding = new UTF8Encoding(false),
|
||||
Indent = true,
|
||||
IndentChars = "".PadLeft(indent),
|
||||
NewLineChars = Environment.NewLine,
|
||||
NewLineHandling = NewLineHandling.Replace,
|
||||
};
|
||||
|
||||
using (XmlWriter writer = XmlWriter.Create(stream, settings))
|
||||
sender.Save(writer);
|
||||
|
||||
rtn = Encoding.UTF8.GetString(stream.ToArray());
|
||||
}
|
||||
|
||||
if (haeder == false)
|
||||
{
|
||||
int index = rtn.IndexOf("<?");
|
||||
if (index >= 0)
|
||||
{
|
||||
index = rtn.IndexOf("<", index + 1);
|
||||
rtn = rtn.Substring(index);
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드를 XmlDocument에 복사합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="document"></param>
|
||||
/// <param name="isChild"></param>
|
||||
public static void CopyValue(this XmlNode sender, XmlDocument document, bool isChild = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = sender.GetFullPath();
|
||||
foreach (XmlNode child in sender.ChildNodes)
|
||||
{
|
||||
if (child.NodeType == XmlNodeType.Text)
|
||||
{
|
||||
XmlNode dest = document.SelectSingleNode(path);
|
||||
if (dest == null) continue;
|
||||
|
||||
if (dest.ChildNodes.Count == 0)
|
||||
{
|
||||
XmlNode valueNode = document.CreateNode("text", "", "");
|
||||
dest.AppendChild(valueNode);
|
||||
}
|
||||
foreach (XmlNode destChild in dest.ChildNodes)
|
||||
if (destChild.NodeType == XmlNodeType.Text) destChild.Value = child.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isChild) child.CopyValue(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 하위 노드를 생성하고 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="innerText"></param>
|
||||
/// <returns></returns>
|
||||
public static XmlNode CreateChildNode(this XmlNode sender, string name, string innerText = "", int index = -1, bool isAfter = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlDocument document = sender.OwnerDocument;
|
||||
XmlNode childNode = document.CreateElement(name);
|
||||
if (!string.IsNullOrEmpty(innerText)) childNode.InnerText = innerText;
|
||||
|
||||
if (index < 0 || index > sender.ChildNodes.Count)
|
||||
{
|
||||
sender.AppendChild(childNode);
|
||||
return childNode;
|
||||
}
|
||||
|
||||
XmlNode refNode = sender.ChildNodes[index];
|
||||
if (isAfter) sender.InsertAfter(childNode, refNode);
|
||||
else sender.InsertBefore(childNode, refNode);
|
||||
|
||||
return childNode;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드를 삭제합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveChildNode(this XmlNode sender, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (index >= sender.ChildNodes.Count) return false;
|
||||
XmlNode node = sender.ChildNodes[index];
|
||||
if (node != null) sender.RemoveChild(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드를 삭제합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveChildNode(this XmlNode sender, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlNode node = sender.GetSingleNodeByName(name);
|
||||
if (node == null) return false;
|
||||
sender.RemoveChild(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드를 삭제합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveChildNodes(this XmlNode sender, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (XmlNode node in sender.GetNodesByName(name))
|
||||
sender.RemoveChild(node);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetFullPath(this XmlNode sender)
|
||||
{
|
||||
if (sender == null) return string.Empty;
|
||||
if (sender.ParentNode == null || sender.ParentNode.NodeType != XmlNodeType.Element)
|
||||
return $"//{sender.Name}";
|
||||
|
||||
return $"{sender.ParentNode.GetFullPath()}/{sender.Name}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 문자열에 있는 잘못된 XML 문자를 해당하는 올바른 XML로 바꿉니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns>잘못된 문자가 있었으나 바뀐 입력 문자열입니다.</returns>
|
||||
public static string XMLEscape(this string sender)
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.Security.SecurityElement.Escape(sender);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 입력 문자열에서 이스케이프된 문자를 변환합니다.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static string XMLUnescape(this string sender)
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.Text.RegularExpressions.Regex.Unescape(sender);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return sender;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
887
JWH/EXTENSIONS/XLogger.cs
Normal file
887
JWH/EXTENSIONS/XLogger.cs
Normal file
@@ -0,0 +1,887 @@
|
||||
using log4net;
|
||||
using log4net.Appender;
|
||||
using log4net.Config;
|
||||
using log4net.Repository.Hierarchy;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
using static log4net.Appender.RollingFileAppender;
|
||||
|
||||
namespace JWH
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// log4net을 활용한 로그작성 라이브러리
|
||||
/// [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
|
||||
/// </summary>
|
||||
public class XLogger
|
||||
{
|
||||
|
||||
#region [ Static ] ====================================================
|
||||
|
||||
/// <summary>
|
||||
/// Logger root
|
||||
/// </summary>
|
||||
public static XLogger Instance { get; set; } = new XLogger();
|
||||
|
||||
/// <summary>
|
||||
/// RollingFileAppender를 생성한다
|
||||
/// </summary>
|
||||
/// <param name="name">Appender.Name</param>
|
||||
/// <param name="file">Appender.File</param>
|
||||
/// <param name="pattern">Appender.ConversionPattern</param>
|
||||
/// <returns></returns>
|
||||
public static RollingFileAppender CreateRollingFileAppender(string name, string path, string pattern)
|
||||
{
|
||||
log4net.Appender.RollingFileAppender appender = new log4net.Appender.RollingFileAppender();
|
||||
try
|
||||
{
|
||||
appender.Name = name;
|
||||
appender.File = $"{path}{name}_";
|
||||
appender.DatePattern = $"yyyyMMddHH'.log'";
|
||||
//appender.MaxSizeRollBackups = 100;
|
||||
appender.MaximumFileSize = "10MB";
|
||||
appender.StaticLogFileName = false;
|
||||
appender.AppendToFile = true;
|
||||
appender.PreserveLogFileNameExtension = true;
|
||||
appender.RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Date;
|
||||
appender.LockingModel = new RollingFileAppender.MinimalLock();
|
||||
//appender.CountDirection = XLogger.GetCountDirection(path, $"{name}_", appender.DatePattern);
|
||||
log4net.Layout.PatternLayout layout = new log4net.Layout.PatternLayout() { ConversionPattern = pattern };
|
||||
layout.ActivateOptions();
|
||||
appender.Layout = layout;
|
||||
appender.ActivateOptions();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
|
||||
return appender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// log4net.GlobalContext.Properties
|
||||
/// <para>You must call ConfigureAndWatch</para>
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void AddProperties(string name, string value)
|
||||
{
|
||||
log4net.GlobalContext.Properties[name] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// log4net.GlobalContext.Properties
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetProperties(string name)
|
||||
{
|
||||
return log4net.GlobalContext.Properties[name] as string;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XmlConfigurator.ConfigureAndWatch
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
public static void ConfigureAndWatch(FileInfo file)
|
||||
{
|
||||
if (file?.Exists == false) return;
|
||||
|
||||
XmlConfigurator.ConfigureAndWatch(file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Enum ] ======================================================
|
||||
|
||||
/// <summary>XLogLevel</summary>
|
||||
public enum eXLogLevel
|
||||
{
|
||||
None = 0,
|
||||
Debug = 1,
|
||||
Info = 2,
|
||||
Warn = 3,
|
||||
Error = 4,
|
||||
Fatal = 5
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Variable ] ==================================================
|
||||
|
||||
/// <summary>Filter Types</summary>
|
||||
private List<Type> m_FilterTypes = new List<Type>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Properties ] ================================================
|
||||
|
||||
/// <summary>Logger Name</summary>
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>log4net.Repository.Hierarchy.Logger</summary>
|
||||
public Logger Logger { get { return this.GetLogger(); } }
|
||||
|
||||
/// <summary>LOG Control</summary>
|
||||
public TextBoxBase Control { get; set; } = null;
|
||||
|
||||
/// <summary>Control.ScrollToCaret</summary>
|
||||
public bool OnScrollToCaret { get; set; } = true;
|
||||
|
||||
/// <summary>LOG Control : 0.DateTime, 1.LogLevel, 2.LogName, 3.ClassFullName, 4.Method, 5.Message, 6.ClassName</summary>
|
||||
/// <example></example>
|
||||
public string ControlPatternLayout { get; set; } = "[{0}] {1} {2} {3}.{4}() {5}";
|
||||
|
||||
/// <summary>Last Deleted LogFile</summary>
|
||||
public DateTime LastDeletedDateTime { get; set; } = DateTime.MinValue;
|
||||
|
||||
/// <summary>Filter Types</summary>
|
||||
public List<Type> FilterTypes
|
||||
{
|
||||
get { return m_FilterTypes; }
|
||||
}
|
||||
|
||||
/// <summary>RichTextBox.SelectionColor</summary>
|
||||
public Color ForeColor { get; set; } = SystemColors.ControlText;
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ XLogger ] ===================================================
|
||||
|
||||
/// <summary>
|
||||
/// XLogger
|
||||
/// </summary>
|
||||
public XLogger()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XLogger
|
||||
/// </summary>
|
||||
/// <param name="name">Logger Name defined in log4net.config</param>
|
||||
public XLogger(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Method ] ====================================================
|
||||
|
||||
#region [ Appender ] --------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// 동적으로 RollingFileAppender를 추가한다
|
||||
/// </summary>
|
||||
public IAppender AddRollingFileAppender(string path, string pattern)
|
||||
{
|
||||
FileAppender appender = null;
|
||||
try
|
||||
{
|
||||
string name = this.Name;
|
||||
appender = XLogger.CreateRollingFileAppender(name, path, pattern);
|
||||
this.AddAppender(appender);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
|
||||
return appender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 동적으로 RollingFileAppender를 추가한다
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="file"></param>
|
||||
/// <param name="pattern"></param>
|
||||
public void AddRollingFileAppender(string name, string file, string pattern)
|
||||
{
|
||||
try
|
||||
{
|
||||
log4net.Repository.Hierarchy.Logger logger = this.Logger;
|
||||
RollingFileAppender appender = XLogger.CreateRollingFileAppender(name, file, pattern);
|
||||
this.AddAppender(appender);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 다른 XLogger의 Appender를 추가한다
|
||||
/// </summary>
|
||||
/// <param name="srcXLogger"></param>
|
||||
/// <param name="index"></param>
|
||||
public void AddRollingFileAppender(XLogger srcXLogger, int index = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
log4net.Repository.Hierarchy.Logger srclogger = srcXLogger.Logger;
|
||||
if (srclogger.Appenders.Count <= index) return;
|
||||
|
||||
IAppender srcAppender = srclogger.Appenders[index];
|
||||
this.AddAppender(srcAppender);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appender를 추가한다
|
||||
/// </summary>
|
||||
/// <param name="appender"></param>
|
||||
public void AddAppender(IAppender appender)
|
||||
{
|
||||
try
|
||||
{
|
||||
log4net.Repository.Hierarchy.Logger logger = this.Logger;
|
||||
FileAppender fileAppender = null;
|
||||
IAppender removeItem = null;
|
||||
foreach (IAppender item in logger.Appenders)
|
||||
{
|
||||
if (item.Name == appender.Name)
|
||||
{
|
||||
removeItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (removeItem != null)
|
||||
{
|
||||
fileAppender = removeItem as FileAppender;
|
||||
logger.RemoveAppender(removeItem).Close();
|
||||
}
|
||||
|
||||
fileAppender = appender as FileAppender;
|
||||
logger.AddAppender(appender);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XLogger.Instance.Fatal(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 Appender를 제거한다
|
||||
/// </summary>
|
||||
public void ClearAppender()
|
||||
{
|
||||
log4net.Repository.Hierarchy.Logger logger = this.Logger;
|
||||
List<IAppender> lstAppender = new List<IAppender>();
|
||||
|
||||
foreach (IAppender item in logger.Appenders)
|
||||
lstAppender.Add(item);
|
||||
|
||||
foreach (IAppender item in lstAppender)
|
||||
logger.RemoveAppender(item).Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ MDC ] -------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// MDC Key
|
||||
/// </summary>
|
||||
private enum eMDCKey
|
||||
{
|
||||
Logger,
|
||||
Name,
|
||||
Class,
|
||||
Method
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set MDC
|
||||
/// </summary>
|
||||
/// <param name="mdcKey"></param>
|
||||
/// <param name="value"></param>
|
||||
private void SetMDC(eMDCKey mdcKey, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
MDC.Set(mdcKey.ToString().ToLower(), value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set MDC
|
||||
/// </summary>
|
||||
/// <param name="mdcKey"></param>
|
||||
/// <param name="value"></param>
|
||||
private void SetMDC(string mdcKey, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
MDC.Set(mdcKey.ToLower(), value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear MDC
|
||||
/// </summary>
|
||||
private void ClearMDC()
|
||||
{
|
||||
foreach (string mdcKey in Enum.GetNames(typeof(eMDCKey)))
|
||||
SetMDC(mdcKey, string.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Filter ] ----------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Add Filter(Type)
|
||||
/// </summary>
|
||||
/// <param name="types"></param>
|
||||
public void AddFilterType(params Type[] types)
|
||||
{
|
||||
m_FilterTypes.AddRange(types);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear Filter(Type)
|
||||
/// </summary>
|
||||
public void ClearFilterType()
|
||||
{
|
||||
m_FilterTypes.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Debug ] -----------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Debug
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Debug(object value = null, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Debug, value, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Debug
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Debug(string message, Exception e, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Debug, message, e, color);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Info ] ------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Info
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Info(object value = null, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Info, value, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Info
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Info(string message, Exception e, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Info, message, e, color);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Warn ] ------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Warn
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Warn(object value = null, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Warn, value, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Warn
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Warn(string message, Exception e, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Warn, message, e, color);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Error ] -----------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Error
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Error(object value = null, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Error, value, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Error
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Error(string message, Exception e, Color? color = null)
|
||||
{
|
||||
return this.WriteLine(eXLogLevel.Error, message, e, color);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ Fatal ] -----------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Fatal
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public string Fatal(object value, bool showMessageBox)
|
||||
{
|
||||
string message = this.WriteLine(eXLogLevel.Fatal, value);
|
||||
|
||||
if (showMessageBox)
|
||||
MessageBox.Show(message, "Fatal", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fatal
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Fatal(object value = null, Color? color = null)
|
||||
{
|
||||
string result = this.WriteLine(eXLogLevel.Fatal, value, color);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fatal
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <param name="color"></param>
|
||||
public string Fatal(string message, Exception e, Color? color = null)
|
||||
{
|
||||
string result = this.WriteLine(eXLogLevel.Fatal, message, e, color);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fatal
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="showMessageBox">Show MessageBox</param>
|
||||
/// <param name="color"></param>
|
||||
private string xFatal(object value = null, bool showMessageBox = false, Color? color = null)
|
||||
{
|
||||
string result = this.WriteLine(eXLogLevel.Fatal, value, color);
|
||||
if (showMessageBox)
|
||||
MessageBox.Show(result, "Fatal", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fatal
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <param name="showMessageBox">Show MessageBox</param>
|
||||
/// <param name="color"></param>
|
||||
private string xFatal(string message, Exception e, bool showMessageBox = false, Color? color = null)
|
||||
{
|
||||
string result = this.WriteLine(eXLogLevel.Fatal, message, e, color);
|
||||
if (showMessageBox)
|
||||
MessageBox.Show(result, "Fatal", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ WriteLine ] -------------------------------------------------
|
||||
|
||||
private StackFrame GetStackFrame(StackTrace trace)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (StackFrame frame in trace.GetFrames())
|
||||
{
|
||||
MethodBase method = frame.GetMethod();
|
||||
if (method.DeclaringType != typeof(XLogger))
|
||||
return frame;
|
||||
}
|
||||
|
||||
return trace.GetFrame(2);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.Message);
|
||||
return trace.GetFrame(2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 문자열 값을 log4net 혹은 표준 출력 스트림에 출력합니다
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="value"></param>
|
||||
public string WriteLine(eXLogLevel level, object value = null, Color? color = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
StackTrace trace = new StackTrace();
|
||||
//StackFrame frame = trace.GetFrame(2);
|
||||
StackFrame frame = this.GetStackFrame(trace);
|
||||
MethodBase method = frame.GetMethod();
|
||||
Exception ex = null;
|
||||
string strMessage = string.Empty;
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
if (value is Exception)
|
||||
{
|
||||
ex = value as Exception;
|
||||
//strMessage = ex.Message;
|
||||
}
|
||||
else
|
||||
{
|
||||
strMessage = value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return WriteLine(level, strMessage, method, ex, color);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.Message);
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 문자열 값을 log4net 혹은 표준 출력 스트림에 출력합니다
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="e"></param>
|
||||
public string WriteLine(eXLogLevel level, string message, Exception e, Color? color = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
StackTrace trace = new StackTrace();
|
||||
//StackFrame frame = trace.GetFrame(2);
|
||||
StackFrame frame = this.GetStackFrame(trace);
|
||||
MethodBase method = frame.GetMethod();
|
||||
string strMessage = string.Empty;
|
||||
|
||||
strMessage = message;
|
||||
|
||||
return WriteLine(level, strMessage, method, e);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.Message);
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 문자열 값을 log4net 혹은 표준 출력 스트림에 출력합니다
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="method"></param>
|
||||
public string WriteLine(eXLogLevel level, string message, MethodBase method, Exception e = null, Color? color = null)
|
||||
{
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
string name = this.Name;
|
||||
string strDTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||
string strClassFullName = string.Empty;
|
||||
string strClassName = string.Empty;
|
||||
string strMethod = string.Empty;
|
||||
string strLog = string.Empty;
|
||||
string strConsole = string.Empty;
|
||||
|
||||
ILog log = LogManager.GetLogger(name);
|
||||
ClearMDC();
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
StackTrace trace = new StackTrace();
|
||||
StackFrame frame = trace.GetFrame(1);
|
||||
method = frame.GetMethod();
|
||||
}
|
||||
|
||||
if (method != null && method.DeclaringType != null)
|
||||
{
|
||||
if (m_FilterTypes.Count > 0 && m_FilterTypes.Contains(method.DeclaringType) == false) return result;
|
||||
|
||||
strClassFullName = method.DeclaringType.FullName;
|
||||
strClassName = method.DeclaringType.Name;
|
||||
strMethod = method.Name;
|
||||
}
|
||||
|
||||
if (message.EndsWith(Environment.NewLine))
|
||||
message = message.Remove(message.Length - Environment.NewLine.Length);
|
||||
strLog = message;
|
||||
strConsole = string.Format(this.ControlPatternLayout, strDTime, level.ToString().ToUpper(), name, strClassFullName, strMethod, message, strClassName);
|
||||
|
||||
SetMDC(eMDCKey.Name, name);
|
||||
SetMDC(eMDCKey.Class, strClassFullName);
|
||||
SetMDC(eMDCKey.Method, strMethod);
|
||||
|
||||
result = $"{strConsole}" + (e != null ? Environment.NewLine + e.ToString() : "");
|
||||
switch (level)
|
||||
{
|
||||
case eXLogLevel.Debug:
|
||||
if (log.IsDebugEnabled) { log.Debug(strLog, e); this.WriteControl(result, color); }
|
||||
break;
|
||||
case eXLogLevel.Info:
|
||||
if (log.IsInfoEnabled) { log.Info(strLog, e); this.WriteControl(result, color); }
|
||||
break;
|
||||
case eXLogLevel.Warn:
|
||||
if (log.IsWarnEnabled) { log.Warn(strLog, e); this.WriteControl(result, color); }
|
||||
break;
|
||||
case eXLogLevel.Error:
|
||||
if (log.IsErrorEnabled) { log.Error(strLog); this.WriteControl(result, color); }
|
||||
break;
|
||||
case eXLogLevel.Fatal:
|
||||
if (log.IsFatalEnabled) { log.Fatal(strLog, e); this.WriteControl(result, color); }
|
||||
break;
|
||||
}
|
||||
|
||||
//this.DeleteRollingFiles();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.ToString());
|
||||
return ex.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Control.Text에 로그를 기록한다
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
private void WriteControl(string message, Color? color = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.Control == null) return;
|
||||
if (color.Equals(Color.Transparent)) return;
|
||||
if (this.Control.InvokeRequired)
|
||||
{
|
||||
this.Control.Invoke((MethodInvoker)delegate { this.WriteControl(message, color); });
|
||||
return;
|
||||
}
|
||||
|
||||
Application.DoEvents();
|
||||
this.Control.SuspendLayout();
|
||||
if (this.Control.MaxLength <= this.Control.TextLength + message.Length)
|
||||
{
|
||||
int count = 0;
|
||||
while (this.Control.MaxLength * 0.9 <= this.Control.TextLength + message.Length)
|
||||
{
|
||||
this.Control.SelectionStart = 0;
|
||||
this.Control.SelectionLength = this.Control.GetFirstCharIndexFromLine(count + 1);
|
||||
this.Control.SelectedText = string.Empty;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
int index = this.Control.TextLength;
|
||||
this.Control.AppendText(message + Environment.NewLine);
|
||||
if (this.Control.GetType() == typeof(RichTextBox))
|
||||
{
|
||||
RichTextBox richTextBox = (RichTextBox)this.Control;
|
||||
if (color == null) color = richTextBox.ForeColor;
|
||||
|
||||
richTextBox.SelectionStart = index;
|
||||
richTextBox.SelectionLength = message.Length;
|
||||
richTextBox.SelectionColor = (Color)color;
|
||||
}
|
||||
|
||||
if (this.OnScrollToCaret)
|
||||
this.Control.ScrollToCaret();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (this.Control != null) this.Control.ResumeLayout();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region [ ETC ] -------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Change LogLevel
|
||||
/// </summary>
|
||||
/// <param name="level"></param>
|
||||
public void SetLevel(log4net.Core.Level level)
|
||||
{
|
||||
Logger logger = this.Logger;
|
||||
logger.Repository.Threshold = logger.Repository.LevelMap["DEBUG"];
|
||||
logger.Level = level;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logger를 반환한다
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private log4net.Repository.Hierarchy.Logger GetLogger(string name = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(name)) name = this.Name;
|
||||
ILog log = LogManager.GetLogger(name);
|
||||
|
||||
log4net.Repository.Hierarchy.Logger logger = log.Logger as log4net.Repository.Hierarchy.Logger;
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RollingAppender 로그파일을 삭제합니다.
|
||||
/// </summary>
|
||||
/// <param name="interval">동작주기(분)</param>
|
||||
/// <remarks>
|
||||
/// RollingMode='Date'일 경우 동작하며,
|
||||
/// MaxSizeRollBackups 값을 보관일로 적용하여 기간이 경과된 파일들을 삭제한다
|
||||
/// </remarks>
|
||||
public void DeleteRollingFiles(int interval = 30)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DateTime.Now.Subtract(this.LastDeletedDateTime).TotalMinutes < interval) return;
|
||||
this.LastDeletedDateTime = DateTime.Now;
|
||||
|
||||
var repositories = LogManager.GetAllRepositories().FirstOrDefault();
|
||||
if (repositories == null) return;
|
||||
|
||||
foreach (IAppender appender in repositories.GetAppenders())
|
||||
{
|
||||
FileAppender fileAppender = appender as FileAppender;
|
||||
RollingFileAppender rollingAppender = appender as RollingFileAppender;
|
||||
if (rollingAppender != null)
|
||||
{
|
||||
int maxSizeRollBackups = rollingAppender.MaxSizeRollBackups;
|
||||
if (maxSizeRollBackups < 1) continue;
|
||||
|
||||
RollingMode rollingStyle = rollingAppender.RollingStyle;
|
||||
if (rollingStyle != RollingMode.Date) continue;
|
||||
|
||||
string path = System.IO.Path.GetDirectoryName(rollingAppender.File);
|
||||
DirectoryInfo directory = new DirectoryInfo(path);
|
||||
|
||||
//string pattern = this.GetDatePatten(rollingAppender.DatePattern);
|
||||
string extension = System.IO.Path.GetExtension(rollingAppender.File);
|
||||
List<FileInfo> files = directory.GetFiles($"*{extension}")
|
||||
.Where(x => DateTime.Now.Subtract(x.CreationTime).TotalDays > maxSizeRollBackups)
|
||||
.OrderBy(x => x.CreationTime).ToList();
|
||||
foreach (FileInfo file in files)
|
||||
{
|
||||
Trace.WriteLine($"Delete {file.FullName}");
|
||||
file.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private string GetDatePatten(string name)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
string pattern = @"'([^']*)'";
|
||||
|
||||
MatchCollection matches = Regex.Matches(name, pattern);
|
||||
for (int i = 0; i < matches.Count; i++)
|
||||
{
|
||||
sb.Append(matches[i].Groups[1].Value);
|
||||
if (i + 1 < matches.Count) sb.Append("*");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string GetCallStack()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try
|
||||
{
|
||||
StackTrace trace = new StackTrace();
|
||||
for (int i = 0; i < trace.FrameCount; i++)
|
||||
{
|
||||
StackFrame frame = trace.GetFrame(i);
|
||||
MethodBase method = frame.GetMethod();
|
||||
sb.AppendLine($"{method?.DeclaringType?.Name}.{method.Name}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user