[성현모] CPXV2 Init
This commit is contained in:
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public static class AppWinControl
|
||||
{
|
||||
public enum eShowType
|
||||
{
|
||||
SW_HIDE = 0, //Hides the window and activates another window.
|
||||
SW_MAXIMIZE = 3, //Maximizes the specified window.
|
||||
SW_MINIMIZE = 6, //Minimizes the specified window and activates the next top-level window in the Z order.
|
||||
SW_RESTORE = 9, //Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
|
||||
SW_SHOW = 5, //Activates the window and displays it in its current size and position.
|
||||
SW_SHOWDEFAULT = 10, //Sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application.
|
||||
SW_SHOWMAXIMIZED = 3, //Activates the window and displays it as a maximized window.
|
||||
SW_SHOWMINIMIZED = 2, //Activates the window and displays it as a minimized window.
|
||||
SW_SHOWMINNOACTIVE = 7, //Displays the window as a minimized window. This value is similar to SW_SHOWMINIMIZED, except the window is not activated.
|
||||
SW_SHOWNA = 8, //Displays the window in its current size and position. This value is similar to SW_SHOW, except that the window is not activated.
|
||||
SW_SHOWNOACTIVATE = 4, //Displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except that the window is not activated.
|
||||
SW_SHOWNORMAL = 1
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr ExtGetWindowRect(IntPtr hWnd, out Rect lpRect);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool ExtPrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int ExtSetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
private const int SW_RESTORE = 9;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr ExtShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
public static IntPtr GetWindowRect(IntPtr hWnd, out Rect lpRect) { return ExtGetWindowRect(hWnd, out lpRect); }
|
||||
public static bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags) { return ExtPrintWindow(hWnd, hdcBlt, nFlags); }
|
||||
public static int SetForegroundWindow(IntPtr hWnd) { return ExtSetForegroundWindow(hWnd); }
|
||||
public static IntPtr ShowWindow(IntPtr hWnd, int nCmdShow) { return ExtShowWindow(hWnd, nCmdShow); }
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,338 @@
|
||||
using System;
|
||||
|
||||
// http://www.codeproject.com/Articles/13756/Detecting-Application-Idleness
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// ApplicationIdleTimer provides a convenient way of
|
||||
/// processing events only during application dormancy.
|
||||
/// Why use this instead of the Application.Idle event?
|
||||
/// That event gets fired EVERY TIME the message stack
|
||||
/// is exhausted, which basically means it fires very
|
||||
/// frequently. With this, you only get events when
|
||||
/// the application is actually idle.
|
||||
/// </summary>
|
||||
public class ApplicationIdleTimer
|
||||
{
|
||||
|
||||
#region Static Members and Events
|
||||
|
||||
// private singleton
|
||||
private static ApplicationIdleTimer instance = null;
|
||||
|
||||
// Notes:
|
||||
// Could have utilized the System.Timers.ElapsedEventArgs, but that
|
||||
// only provides the time an event happend (even though it's called
|
||||
// "Elapsed" not "Timed" EventArgs). I figgure most listeners care
|
||||
// less *WHEN* the app went idle, but rather *HOW LONG* it has been
|
||||
// idle.
|
||||
|
||||
/// <summary>
|
||||
/// EventArgs for an ApplicationIdle event.
|
||||
/// </summary>
|
||||
public class ApplicationIdleEventArgs : EventArgs
|
||||
{
|
||||
// time of last idle
|
||||
private DateTime _idleSince;
|
||||
// duration of "idleness"
|
||||
private TimeSpan _idleTime;
|
||||
|
||||
/// <summary>
|
||||
/// Internal constructor
|
||||
/// </summary>
|
||||
/// <param name="idleSince">Time app was declared idle</param>
|
||||
internal ApplicationIdleEventArgs(DateTime idleSince) : base()
|
||||
{
|
||||
_idleSince = idleSince;
|
||||
_idleTime = new TimeSpan(DateTime.Now.Ticks - idleSince.Ticks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp of the last time the application was "active".
|
||||
/// </summary>
|
||||
public DateTime IdleSince
|
||||
{
|
||||
get { return _idleSince; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Duration of time the application has been idle.
|
||||
/// </summary>
|
||||
public TimeSpan IdleDuration
|
||||
{
|
||||
get { return _idleTime; }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// ApplicationIdle event handler.
|
||||
/// </summary>
|
||||
public delegate void ApplicationIdleEventHandler(ApplicationIdleEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Hook into the ApplicationIdle event to monitor inactivity.
|
||||
/// It will fire AT MOST once per second.
|
||||
/// </summary>
|
||||
public static event ApplicationIdleEventHandler ApplicationIdle;
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
// Timer used to guarentee perodic updates.
|
||||
private System.Timers.Timer _timer;
|
||||
|
||||
// Tracks idle state
|
||||
private bool isIdle;
|
||||
// Last time application was declared "idle"
|
||||
private System.DateTime lastAppIdleTime;
|
||||
// Last time we checked for GUI activity
|
||||
private long lastIdleCheckpoint;
|
||||
// Running count of Application.Idle events recorded since a checkpoint.
|
||||
// Expressed as a long (instead of int) for math.
|
||||
private long idlesSinceCheckpoint;
|
||||
// Number of ticks used by application process at last checkpoint
|
||||
private long cpuTime;
|
||||
// Last time we checked for cpu activity
|
||||
private long lastCpuCheckpoint;
|
||||
|
||||
// These values can be adjusted through the static properties:
|
||||
// Maximum "activity" (Application.Idle events per second) that will be considered "idle"
|
||||
// Here it is expressed as minimum ticks between idles.
|
||||
private long guiThreshold = TimeSpan.TicksPerMillisecond * 50L;
|
||||
// Maximum CPU use (percentage) that is considered "idle"
|
||||
private double cpuThreshold = 0.05;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Private constructor. One instance is plenty.
|
||||
/// </summary>
|
||||
private ApplicationIdleTimer()
|
||||
{
|
||||
// Initialize counters
|
||||
isIdle = false;
|
||||
lastAppIdleTime = DateTime.Now;
|
||||
lastIdleCheckpoint = lastCpuCheckpoint = DateTime.UtcNow.Ticks;
|
||||
idlesSinceCheckpoint = cpuTime = 0;
|
||||
|
||||
// Set up the timer and the counters
|
||||
_timer = new System.Timers.Timer(500); // every half-second.
|
||||
_timer.Enabled = true;
|
||||
_timer.Start();
|
||||
|
||||
// Hook into the events
|
||||
_timer.Elapsed += new System.Timers.ElapsedEventHandler(Heartbeat);
|
||||
System.Windows.Forms.Application.Idle += new EventHandler(Application_Idle);
|
||||
}
|
||||
/// <summary>
|
||||
/// Static initialization. Called once per AppDomain.
|
||||
/// </summary>
|
||||
static ApplicationIdleTimer()
|
||||
{
|
||||
// Create the singleton.
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new ApplicationIdleTimer();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void Heartbeat(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
// First we need to do here is compensate for the
|
||||
// "heartbeat", since it will result in an 'extra'
|
||||
// Idle firing .. just don't cause a divide by zero!
|
||||
if (idlesSinceCheckpoint > 1)
|
||||
idlesSinceCheckpoint--;
|
||||
|
||||
bool newIdle = isIdle;
|
||||
long delta = DateTime.UtcNow.Ticks - lastIdleCheckpoint;
|
||||
|
||||
// Determine average idle events per second. Done manually here
|
||||
// instead of using the ComputeGUIActivity() method to avoid the
|
||||
// unnecessary numeric conversion and use of a TimeSpan object.
|
||||
if (delta >= TimeSpan.TicksPerSecond)
|
||||
{
|
||||
// It's been over a second since last checkpoint,
|
||||
// so determine how "busy" the app has been over that timeframe.
|
||||
if (idlesSinceCheckpoint == 0 || delta / idlesSinceCheckpoint >= guiThreshold)
|
||||
{
|
||||
// Minimal gui activity. Check recent CPU activity.
|
||||
if (cpuThreshold < 1.0)
|
||||
newIdle = (ComputeCPUUsage(true) < cpuThreshold);
|
||||
else
|
||||
newIdle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newIdle = false;
|
||||
}
|
||||
|
||||
// Update counters if state changed.
|
||||
if (newIdle != isIdle)
|
||||
{
|
||||
isIdle = newIdle;
|
||||
if (newIdle)
|
||||
lastAppIdleTime = DateTime.Now.AddTicks(-1L * delta);
|
||||
}
|
||||
|
||||
// Reset checkpoint.
|
||||
lastIdleCheckpoint = DateTime.UtcNow.Ticks;
|
||||
idlesSinceCheckpoint = 0;
|
||||
|
||||
// Last but not least, if idle, raise the event.
|
||||
if (newIdle)
|
||||
OnApplicationIdle();
|
||||
}
|
||||
}
|
||||
private void Application_Idle(object sender, EventArgs e)
|
||||
{
|
||||
// Increment idle counter.
|
||||
idlesSinceCheckpoint++;
|
||||
}
|
||||
|
||||
internal double ComputeCPUUsage(bool resetCounters)
|
||||
{
|
||||
long delta = DateTime.UtcNow.Ticks - lastCpuCheckpoint;
|
||||
double pctUse = 0.0;
|
||||
try
|
||||
{
|
||||
// Get total time this process has used the cpu.
|
||||
long cpu = System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime.Ticks;
|
||||
|
||||
// Compute usage.
|
||||
if (delta > 0)
|
||||
pctUse = ((double)(cpu - cpuTime)) / (double)delta;
|
||||
else
|
||||
pctUse = ((cpu - cpuTime) == 0 ? 0.0 : 1.0);
|
||||
|
||||
// Update counter and checkpoint if told OR if delta is at least a quarter second.
|
||||
// This is to prevent inaccurate readings due to frequent OR infrequent calls.
|
||||
if (resetCounters || 4L * delta >= TimeSpan.TicksPerSecond)
|
||||
{
|
||||
lastCpuCheckpoint = DateTime.UtcNow.Ticks;
|
||||
cpuTime = cpu;
|
||||
|
||||
// Update idle status if above threshold.
|
||||
if (!resetCounters && isIdle && pctUse > cpuThreshold)
|
||||
isIdle = false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Probably a security thing. Just ignore.
|
||||
pctUse = double.NaN;
|
||||
}
|
||||
return pctUse;
|
||||
}
|
||||
|
||||
internal double ComputeGUIActivity()
|
||||
{
|
||||
if (idlesSinceCheckpoint <= 0) return 0.0;
|
||||
|
||||
TimeSpan delta = new TimeSpan(DateTime.UtcNow.Ticks - lastIdleCheckpoint);
|
||||
if (delta.Ticks == 0)
|
||||
{
|
||||
// Clock hasn't updated yet. Return a "real" value
|
||||
// based on counter (either 0 or twice the threshold).
|
||||
return (idlesSinceCheckpoint == 0 ? 0.0 : ((double)TimeSpan.TicksPerSecond / (double)instance.guiThreshold) * 2.0);
|
||||
}
|
||||
|
||||
// Expressed as activity (number of idles) per second.
|
||||
return ((double)idlesSinceCheckpoint / delta.TotalSeconds);
|
||||
|
||||
// Note that this method, unlike his CPU brother, does not reset any counters.
|
||||
// The gui activity counters are reset once a second by the Heartbeat.
|
||||
}
|
||||
private void OnApplicationIdle()
|
||||
{
|
||||
// Check to see if anyone cares.
|
||||
if (ApplicationIdle == null) return;
|
||||
|
||||
// Build the message
|
||||
ApplicationIdleEventArgs e = new ApplicationIdleEventArgs(this.lastAppIdleTime);
|
||||
|
||||
// Iterate over all listeners
|
||||
foreach (MulticastDelegate multicast in ApplicationIdle.GetInvocationList())
|
||||
{
|
||||
// Raise the event
|
||||
multicast.DynamicInvoke(new object[] { e });
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static Properties
|
||||
/// <summary>
|
||||
/// Returns the percent CPU use for the current process (0.0-1.0).
|
||||
/// Will return double.NaN if indeterminate.
|
||||
/// </summary>
|
||||
public static double CurrentCPUUsage
|
||||
{
|
||||
get { return instance.ComputeCPUUsage(false); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an "indication" of the gui activity, expressed as
|
||||
/// activity per second. 0 indicates no activity.
|
||||
/// GUI activity includes user interactions (typing,
|
||||
/// moving mouse) as well as events, paint operations, etc.
|
||||
/// </summary>
|
||||
public static double CurrentGUIActivity
|
||||
{
|
||||
get { return instance.ComputeGUIActivity(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the *last determined* idle state. Idle state is
|
||||
/// recomputed once per second. Both the gui and the cpu must
|
||||
/// be idle for this property to be true.
|
||||
/// </summary>
|
||||
public static bool IsIdle
|
||||
{
|
||||
get { return instance.isIdle; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The threshold (gui activity) for determining idleness.
|
||||
/// GUI activity below this level is considered "idle".
|
||||
/// </summary>
|
||||
public static double GUIActivityThreshold
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((double)TimeSpan.TicksPerSecond / (double)instance.guiThreshold);
|
||||
}
|
||||
set
|
||||
{
|
||||
// validate value
|
||||
if (value <= 0.0)
|
||||
throw new ArgumentOutOfRangeException("GUIActivityThreshold", value, "GUIActivityThreshold must be greater than zero.");
|
||||
|
||||
instance.guiThreshold = (long)((double)TimeSpan.TicksPerSecond / value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The threshold (cpu usage) for determining idleness.
|
||||
/// CPU usage below this level is considered "idle".
|
||||
/// A value >= 1.0 will disable CPU idle checking.
|
||||
/// </summary>
|
||||
public static double CPUUsageThreshold
|
||||
{
|
||||
get { return instance.cpuThreshold; }
|
||||
set
|
||||
{
|
||||
if (value == instance.cpuThreshold)
|
||||
return;
|
||||
|
||||
// validate value
|
||||
if (value < 0.0)
|
||||
throw new ArgumentOutOfRangeException("CPUUsageThreshold", value, "Negative values are not allowed.");
|
||||
|
||||
instance.cpuThreshold = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,301 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using static SystemX.Net.Platform.Common.Util.LogMessage;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public static class ConsoleUtil
|
||||
{
|
||||
static bool ConsoleShowState = false;
|
||||
|
||||
const int SW_HIDE = 0;
|
||||
const int SW_SHOW = 5;
|
||||
|
||||
// STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
|
||||
const int STD_INPUT_HANDLE = -10;
|
||||
|
||||
/// <summary>
|
||||
/// SC_CLOSE
|
||||
/// </summary>
|
||||
private const uint SC_CLOSE = 0xf060;
|
||||
|
||||
/// <summary>
|
||||
/// MF_ENABLED
|
||||
/// </summary>
|
||||
private const uint MF_ENABLED = 0x00000000;
|
||||
|
||||
/// <summary>
|
||||
/// MF_GRAYED
|
||||
/// </summary>
|
||||
private const uint MF_GRAYED = 0x00000001;
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern IntPtr GetConsoleWindow();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
static extern IntPtr GetStdHandle(int nStdHandle);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
#region 시스템 메뉴 구하기 - GetSystemMenu(windowHandle, revert)
|
||||
|
||||
/// <summary>
|
||||
/// 시스템 메뉴 구하기
|
||||
/// </summary>
|
||||
/// <param name="windowHandle">윈도우 핸들</param>
|
||||
/// <param name="revert">메뉴 복사 핸들 여부</param>
|
||||
/// <returns>시스템 메뉴 핸들</returns>
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetSystemMenu(IntPtr windowHandle, bool revert);
|
||||
|
||||
#endregion
|
||||
#region 메뉴 항목 이용 가능 여부 설정하기 - EnableMenuItem(menuHandle, menuItemID, enabled)
|
||||
|
||||
/// <summary>
|
||||
/// 메뉴 항목 이용 가능 여부 설정하기
|
||||
/// </summary>
|
||||
/// <param name="menuHandle">메뉴 핸들</param>
|
||||
/// <param name="menuItemID">메뉴 항목 ID</param>
|
||||
/// <param name="enabled">이용 가능 여부</param>
|
||||
/// <returns>처리 결과</returns>
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool EnableMenuItem(IntPtr menuHandle, uint menuItemID, uint enabled);
|
||||
#endregion
|
||||
|
||||
public static void ConsoleVisibleControl()
|
||||
{
|
||||
var handle = GetConsoleWindow();
|
||||
|
||||
if (ConsoleShowState)
|
||||
ConsoleHide(handle);
|
||||
else
|
||||
ConsoleShow(handle);
|
||||
}
|
||||
|
||||
public static void ConsoleHide()
|
||||
{
|
||||
var handle = GetConsoleWindow();
|
||||
var consoleHandle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
||||
const uint ENABLE_QUICK_EDIT = 0x0040;
|
||||
const uint ENABLE_MOUSE_INPUT = 0x0010;
|
||||
|
||||
uint consoleMode = 0x0;
|
||||
|
||||
// get current console mode
|
||||
if (!GetConsoleMode(consoleHandle, out consoleMode))
|
||||
{
|
||||
// Error: Unable to get console mode.
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the quick edit bit in the mode flags
|
||||
consoleMode &= ~ENABLE_QUICK_EDIT;
|
||||
consoleMode &= ~ENABLE_MOUSE_INPUT;
|
||||
|
||||
// set the new mode
|
||||
if (!SetConsoleMode(consoleHandle, consoleMode))
|
||||
{
|
||||
//ERROR: Unable to set console mode
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide
|
||||
ShowWindow(handle, SW_HIDE);
|
||||
|
||||
ConsoleShowState = false;
|
||||
}
|
||||
|
||||
public static void ConsoleHide(IntPtr handle)
|
||||
{
|
||||
// Hide
|
||||
ShowWindow(handle, SW_HIDE);
|
||||
|
||||
ConsoleShowState = false;
|
||||
}
|
||||
|
||||
public static void ConsoleShow(IntPtr handle)
|
||||
{
|
||||
// Show
|
||||
SetCloseButtonEnabled(handle, false);
|
||||
|
||||
ShowWindow(handle, SW_SHOW);
|
||||
|
||||
ConsoleShowState = true;
|
||||
}
|
||||
|
||||
private static void SetCloseButtonEnabled(IntPtr windowHandle, bool enabled)
|
||||
{
|
||||
IntPtr systemMenuHandle = GetSystemMenu(windowHandle, false);
|
||||
|
||||
EnableMenuItem(systemMenuHandle, SC_CLOSE, (uint)(MF_ENABLED | (enabled ? MF_ENABLED : MF_GRAYED)));
|
||||
}
|
||||
}
|
||||
public static class CommonUtil
|
||||
{
|
||||
|
||||
public static string GetProfilePath(string programName = "", bool makeDirOnDemand = true)
|
||||
{
|
||||
var xProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
var dir = String.Format(@"{0}\TESTApp\{1}", xProfilePath, programName);
|
||||
if (makeDirOnDemand && !Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
public static PropertyInfo GetProperty(object obj, string propName)
|
||||
{
|
||||
return obj.GetType().GetProperty(propName);
|
||||
}
|
||||
|
||||
public static void ClonePropertyValues<T>(T original, T clone)
|
||||
{
|
||||
foreach (_PropertyInfo info in original.GetType().GetProperties())
|
||||
SetPropertyValue(clone, info.Name, info.GetValue(original, null));
|
||||
}
|
||||
|
||||
public static T GetPropertyValue<T>(object obj, string propName)
|
||||
{
|
||||
return (T)obj.GetType().GetProperty(propName).GetValue(obj, null);
|
||||
}
|
||||
|
||||
public static void SetPropertyValue(object obj, string propName, object value)
|
||||
{
|
||||
obj.GetType().GetProperty(propName).SetValue(obj, value, null);
|
||||
}
|
||||
|
||||
public static Type GetType(string strType)
|
||||
{
|
||||
try
|
||||
{
|
||||
Type typeResult = Type.GetType("System." + strType, true, true);
|
||||
|
||||
return typeResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageOutput.ConsoleWrite("Type Recognition Error: " + ex.Message, ConsoleColor.Red, LogMessageLevel.FATAL);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Type GetType(Assembly assy, string strNameSpace, string strType)
|
||||
{
|
||||
try
|
||||
{
|
||||
string strFullName = $"{strNameSpace}." + strType;
|
||||
Type typeResult = Type.GetType(strFullName, true, true);
|
||||
|
||||
return typeResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageOutput.ConsoleWrite("Type Recognition Error: " + ex.Message, ConsoleColor.Red, LogMessageLevel.FATAL);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetStringFromASCII(int[] arrData, bool bReverseBit = false)
|
||||
{
|
||||
string sData = string.Empty;
|
||||
foreach (short s in arrData)
|
||||
{
|
||||
byte[] intBytes = BitConverter.GetBytes(s);
|
||||
|
||||
byte ucRever;
|
||||
if (bReverseBit)
|
||||
{
|
||||
ucRever = intBytes[0];
|
||||
intBytes[0] = intBytes[1];
|
||||
intBytes[1] = ucRever;
|
||||
}
|
||||
|
||||
foreach (byte b in intBytes)
|
||||
{
|
||||
if (b == 0)
|
||||
continue;
|
||||
|
||||
sData += ((Char)b).ToString(); // Ascii To Char
|
||||
}
|
||||
}
|
||||
return sData;
|
||||
}
|
||||
|
||||
public static short[] HexStringToBytes(string hexString)
|
||||
{
|
||||
if (hexString.Length % 2 != 0)
|
||||
hexString += "\0";
|
||||
|
||||
char[] result = hexString.ToCharArray();
|
||||
short[] arrShort = new short[hexString.Length / 2];
|
||||
byte[] bytes = new byte[hexString.Length];
|
||||
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
bytes[i] = Convert.ToByte(result[i]);
|
||||
|
||||
for (int i = 0; i < bytes.Length; i += 2)
|
||||
arrShort[i / 2] = BitConverter.ToInt16(bytes, i);
|
||||
|
||||
return arrShort;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class NativeMethods
|
||||
{
|
||||
[DllImportAttribute("kernel32.dll", SetLastError = true, EntryPoint = "CreateFile")]
|
||||
public static extern SafeFileHandle CreateFileW(
|
||||
[InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName,
|
||||
uint dwDesiredAccess,
|
||||
uint dwShareMode,
|
||||
[InAttribute()] System.IntPtr lpSecurityAttributes,
|
||||
uint dwCreationDisposition,
|
||||
uint dwFlagsAndAttributes,
|
||||
[InAttribute()] System.IntPtr hTemplateFile
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern IntPtr CreateFile(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string filename,
|
||||
[MarshalAs(UnmanagedType.U4)] FileAccess access,
|
||||
[MarshalAs(UnmanagedType.U4)] FileShare share,
|
||||
IntPtr securityAttributes,
|
||||
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
|
||||
[MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
|
||||
IntPtr templateFile);
|
||||
}
|
||||
|
||||
public partial class NativeConstants
|
||||
{
|
||||
|
||||
/// GENERIC_WRITE -> (0x40000000L)
|
||||
public const int GENERIC_WRITE = 1073741824;
|
||||
|
||||
public const uint GENERIC_READ = 2147483648;
|
||||
|
||||
/// FILE_SHARE_DELETE -> 0x00000004
|
||||
public const int FILE_SHARE_DELETE = 4;
|
||||
|
||||
/// FILE_SHARE_WRITE -> 0x00000002
|
||||
public const int FILE_SHARE_WRITE = 2;
|
||||
|
||||
/// FILE_SHARE_READ -> 0x00000001
|
||||
public const int FILE_SHARE_READ = 1;
|
||||
|
||||
/// OPEN_ALWAYS -> 4
|
||||
public const int OPEN_ALWAYS = 4;
|
||||
public const int CREATE_NEW = 1;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Subclass should have re-implemented the method by overriding, but it did not.
|
||||
/// </summary>
|
||||
public class NotReimplementedException : NotImplementedException
|
||||
{
|
||||
public NotReimplementedException() { }
|
||||
public NotReimplementedException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subclass will not re-implemented. So you should not call this subclass method.
|
||||
/// </summary>
|
||||
public class WillNotBeReimplementedException : NotImplementedException
|
||||
{
|
||||
public WillNotBeReimplementedException() { }
|
||||
public WillNotBeReimplementedException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
public class UnexpectedCaseOccurredException : InvalidOperationException
|
||||
{
|
||||
public UnexpectedCaseOccurredException() { }
|
||||
public UnexpectedCaseOccurredException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
public class SampleException : Exception
|
||||
{
|
||||
public SampleException() { }
|
||||
public SampleException(string message) : base(message) { }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,252 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public static class FileSystemUtil
|
||||
{
|
||||
public static void DeleteFile(string strSourcePath)
|
||||
{
|
||||
if (!File.Exists(strSourcePath))
|
||||
return;
|
||||
|
||||
File.Delete(strSourcePath);
|
||||
}
|
||||
public static void CopyToDestination(string strSourcePath, string strDesitinationPath, bool bDeleteSrc, bool bOverwrite)
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(strDesitinationPath)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(strDesitinationPath));
|
||||
|
||||
File.Copy(strSourcePath, strDesitinationPath, bOverwrite);
|
||||
|
||||
while(true)
|
||||
{
|
||||
FileInfo fileSrc = new FileInfo(strSourcePath);
|
||||
FileInfo fileDest = new FileInfo(strDesitinationPath);
|
||||
|
||||
if (fileSrc.Length == fileDest.Length)
|
||||
break;
|
||||
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
|
||||
if (bDeleteSrc)
|
||||
DeleteFile(strSourcePath);
|
||||
}
|
||||
|
||||
public static void Compress(DirectoryInfo directorySelected, string strFilePath)
|
||||
{
|
||||
using (var fileStream = new FileStream(strFilePath, FileMode.OpenOrCreate))
|
||||
{
|
||||
using (ZipArchive zip = new ZipArchive(fileStream, ZipArchiveMode.Create))
|
||||
{
|
||||
foreach (FileInfo file in directorySelected.GetFiles())
|
||||
{
|
||||
var entry = zip.CreateEntry(file.Name, CompressionLevel.Optimal);
|
||||
using (Stream s = entry.Open())
|
||||
{
|
||||
FileStream file2Comp = new FileStream(file.FullName, FileMode.Open);
|
||||
|
||||
byte[] data = new byte[file2Comp.Length];
|
||||
file2Comp.Read(data, 0, (int)file2Comp.Length);
|
||||
s.Write(data, 0, data.Length);
|
||||
|
||||
file2Comp.Close();
|
||||
s.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddFile2CompFile(List<string> vstrTargetFilePath, string strCompFilePath)
|
||||
{
|
||||
using (var fileStream = new FileStream(strCompFilePath, FileMode.OpenOrCreate))
|
||||
{
|
||||
using (ZipArchive zip = new ZipArchive(fileStream, ZipArchiveMode.Create))
|
||||
{
|
||||
foreach (string strFilePath in vstrTargetFilePath)
|
||||
{
|
||||
string strTargetFileName = Path.GetFileName(strFilePath);
|
||||
var entry = zip.CreateEntry(strTargetFileName, CompressionLevel.Optimal);
|
||||
|
||||
using (Stream s = entry.Open())
|
||||
{
|
||||
FileStream file2Comp = new FileStream(strFilePath, FileMode.Open);
|
||||
|
||||
byte[] data = new byte[file2Comp.Length];
|
||||
file2Comp.Read(data, 0, (int)file2Comp.Length);
|
||||
s.Write(data, 0, data.Length);
|
||||
|
||||
file2Comp.Close();
|
||||
s.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileStream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void CompressStream2CompFile(List<KeyValuePair<string, MemoryStream>> vPairTargetData, string strCompFilePath)
|
||||
{
|
||||
using (var fileStream = new FileStream(strCompFilePath, FileMode.OpenOrCreate))
|
||||
{
|
||||
using (ZipArchive zip = new ZipArchive(fileStream, ZipArchiveMode.Create))
|
||||
{
|
||||
foreach (KeyValuePair<string, MemoryStream> dataBinFile in vPairTargetData)
|
||||
{
|
||||
var entry = zip.CreateEntry(dataBinFile.Key, CompressionLevel.Optimal);
|
||||
|
||||
using (Stream s = entry.Open())
|
||||
{
|
||||
byte[] data = new byte[dataBinFile.Value.Length];
|
||||
s.Write(dataBinFile.Value.ToArray(), 0, data.Length);
|
||||
|
||||
s.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Decompress(string strPathZip, string strPath)
|
||||
{
|
||||
if (!Directory.Exists(strPath))
|
||||
Directory.CreateDirectory(strPath);
|
||||
|
||||
using (ZipArchive archive = ZipFile.OpenRead(strPathZip))
|
||||
{
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
entry.ExtractToFile(Path.Combine(strPath, entry.FullName), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string> GetFileList(string strPathZip)
|
||||
{
|
||||
List<string> vstrFileNames = new List<string>();
|
||||
|
||||
using (ZipArchive archive = ZipFile.OpenRead(strPathZip))
|
||||
{
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
vstrFileNames.Add(entry.FullName);
|
||||
}
|
||||
|
||||
return vstrFileNames;
|
||||
}
|
||||
|
||||
public static bool IsFileExist(string strPathZip, string strFile)
|
||||
{
|
||||
using (ZipArchive archive = ZipFile.OpenRead(strPathZip))
|
||||
{
|
||||
ZipArchiveEntry entry = archive.Entries.Where(compFile => compFile.FullName == strFile).DefaultIfEmpty()?.First();
|
||||
|
||||
if (entry != null)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static MemoryStream OpenCompressWithoutUnzip(string strPathZip, string strFile)
|
||||
{
|
||||
Stream streamFile = null;
|
||||
|
||||
using (ZipArchive archive = ZipFile.OpenRead(strPathZip))
|
||||
{
|
||||
ZipArchiveEntry entry = archive.Entries.Where(compFile => compFile.FullName == strFile).DefaultIfEmpty()?.First();
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
streamFile = entry.Open();
|
||||
|
||||
return CopyToMemory(streamFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static MemoryStream OpenCompressWithoutUnzip(Stream streamZip, string strFile)
|
||||
{
|
||||
Stream streamFile = null;
|
||||
|
||||
if (streamZip == null)
|
||||
return null;
|
||||
|
||||
using (ZipArchive archive = new ZipArchive(streamZip))
|
||||
{
|
||||
ZipArchiveEntry entry = archive.Entries.Where(compFile => compFile.FullName == strFile).DefaultIfEmpty()?.First();
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
streamFile = entry.Open();
|
||||
|
||||
return CopyToMemory(streamFile);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MemoryStream CopyToMemory(Stream input)
|
||||
{
|
||||
// It won't matter if we throw an exception during this method;
|
||||
// we don't *really* need to dispose of the MemoryStream, and the
|
||||
// caller should dispose of the input stream
|
||||
MemoryStream ret = new MemoryStream();
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
int bytesRead;
|
||||
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
ret.Write(buffer, 0, bytesRead);
|
||||
}
|
||||
// Rewind ready for reading (typical scenario)
|
||||
ret.Position = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static public void ClearDirectory(string strFolderPath)
|
||||
{
|
||||
if (Directory.Exists(strFolderPath))
|
||||
Directory.Delete(strFolderPath, true);
|
||||
}
|
||||
|
||||
static public void ClearFile(string strFilePath)
|
||||
{
|
||||
if (File.Exists(strFilePath))
|
||||
File.Delete(strFilePath);
|
||||
}
|
||||
|
||||
static public void MoveFile(string source, string destination)
|
||||
{
|
||||
if (!File.Exists(source))
|
||||
return;
|
||||
|
||||
if (!Directory.Exists(Path.GetDirectoryName(destination)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(destination));
|
||||
|
||||
// 2017.04.13 add M.S Ko
|
||||
if (File.Exists(destination))
|
||||
{
|
||||
File.Delete(destination);
|
||||
|
||||
LogMessage.MessageOutput.ConsoleWrite("File was deleted & moved name of " + destination, ConsoleColor.White);
|
||||
}
|
||||
|
||||
File.Move(source, destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// see http://www.thecoolestdolphin.be/?p=38
|
||||
/// TextBox 에서 invalid 문자를 filtering 함
|
||||
/// sister classes : Dsu.Common.Utilities.NumericTextBox
|
||||
/// </summary>
|
||||
public class FilterableTextBox : TextBox
|
||||
{
|
||||
/// <summary>
|
||||
/// 허용 문자 set.
|
||||
/// <para/> - empty 이면, ForbiddenCharacterSet 이외의 모든 문자 허용
|
||||
/// <para/> - empty 가 아니면 ForbiddenCharacterSet 는 의미가 없음
|
||||
/// </summary>
|
||||
public string AllowedCharacterSet { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 금칙 문자 set. AllowedCharacterSet 가 empty 인 경우에만 의미를 가짐
|
||||
/// </summary>
|
||||
public string ForbiddenCharacterSet { get; set; }
|
||||
|
||||
public bool ShowBalloonTips { get { return _showBalloonTips; } set { _showBalloonTips = value; }}
|
||||
private bool _showBalloonTips = true;
|
||||
private ToolTip _balloonTips;
|
||||
|
||||
public FilterableTextBox()
|
||||
{
|
||||
// default 는 alpha numeric 만 받음. 필요시 override.
|
||||
SetAlphaNumericFilter();
|
||||
|
||||
_balloonTips = new ToolTip()
|
||||
{
|
||||
ToolTipTitle = "Invalid character.",
|
||||
ToolTipIcon = ToolTipIcon.Warning,
|
||||
AutoPopDelay = 0,
|
||||
ShowAlways = false,
|
||||
};
|
||||
}
|
||||
protected override void OnKeyPress(KeyPressEventArgs e)
|
||||
{
|
||||
base.OnKeyPress(e);
|
||||
_balloonTips.Hide(this);
|
||||
|
||||
if ( Char.IsControl(e.KeyChar) || e.KeyChar == 46 ) // 8==backspace, 13=enter, 46=DEL
|
||||
return;
|
||||
|
||||
bool valid = true;
|
||||
if (String.IsNullOrEmpty(AllowedCharacterSet)) // 허용 문자를 지정하지 않은 경우. 금칙 문자에 포함되지 않으면 OK
|
||||
{
|
||||
if (!String.IsNullOrEmpty(ForbiddenCharacterSet) && ForbiddenCharacterSet.Contains(e.KeyChar))
|
||||
valid = false;
|
||||
}
|
||||
else // 허용 문자를 지정한 경우
|
||||
valid = AllowedCharacterSet.Contains(e.KeyChar);
|
||||
|
||||
|
||||
e.Handled = ! valid;
|
||||
|
||||
if ( ! valid && _showBalloonTips)
|
||||
_balloonTips.Show(String.Format("The character \"{0}\" is invalid.", e.KeyChar), this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Alpha-numeric 문자열 + addition 이 아니면 filtering 한다.
|
||||
/// </summary>
|
||||
/// <param name="addition"></param>
|
||||
public void SetAlphaNumericFilter(string addition="")
|
||||
{
|
||||
AllowedCharacterSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + addition;
|
||||
ForbiddenCharacterSet = String.Empty;
|
||||
}
|
||||
|
||||
public void SetFileNameFilter()
|
||||
{
|
||||
AllowedCharacterSet = String.Empty;
|
||||
ForbiddenCharacterSet = @"\/:*?""<>|";
|
||||
}
|
||||
|
||||
public void SetSymbolFilter(string addition="")
|
||||
{
|
||||
SetAlphaNumericFilter("@_?" + addition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic event argument decorator class
|
||||
/// </summary>
|
||||
public class GenericEventArgs : EventArgs
|
||||
{
|
||||
private EventArgs _innerEventArgs;
|
||||
|
||||
public T Cast<T>() where T : EventArgs
|
||||
{
|
||||
if (_innerEventArgs is T)
|
||||
return (T)_innerEventArgs;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public GenericEventArgs(EventArgs args)
|
||||
{
|
||||
_innerEventArgs = args;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.Common.Util
|
||||
{
|
||||
public static class Gzip
|
||||
{
|
||||
#region Functions
|
||||
public static string Compress(string stringData)
|
||||
{
|
||||
var rowData = Encoding.UTF8.GetBytes(stringData);
|
||||
byte[] compressedData = null;
|
||||
using (var outStream = new MemoryStream())
|
||||
{
|
||||
using (var gStream = new GZipStream(outStream, CompressionMode.Compress))
|
||||
{
|
||||
gStream.Write(rowData, 0, rowData.Length);
|
||||
}
|
||||
compressedData = outStream.ToArray();
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(compressedData);
|
||||
}
|
||||
|
||||
public static string Decompression(string compressedDataStr)
|
||||
{
|
||||
string output = null;
|
||||
byte[] compressedData = Convert.FromBase64String(compressedDataStr);
|
||||
using (var decompressStream = new MemoryStream(compressedData))
|
||||
{
|
||||
using (var gStream = new GZipStream(decompressStream, CompressionMode.Decompress))
|
||||
{
|
||||
using (var reader = new StreamReader(gStream))
|
||||
{
|
||||
output = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region String Extension(확장메서드)
|
||||
public static string GzipCompress(this string stringData)
|
||||
{
|
||||
return Compress(stringData);
|
||||
}
|
||||
|
||||
public static string GzipDecompress(this string compressedDataStr)
|
||||
{
|
||||
return Decompression(compressedDataStr);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using log4net;
|
||||
using log4net.Appender;
|
||||
using SystemX.Net.Platform.Common.ExtensionMethods;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public static class Log4NetWrapper
|
||||
{
|
||||
private static readonly LogProxy _dummyLogger = LogProxy.CreateLoggerProxy(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private static ILog _logger = null;
|
||||
public static ILog Logger { get { return _logger ?? _dummyLogger.Logger; } set { _logger = value; } }
|
||||
|
||||
|
||||
#region Extension methods
|
||||
[Conditional("DEBUG")]
|
||||
public static void DEBUG(this ILog logger, object message, Exception exception)
|
||||
{
|
||||
if (logger.IsDebugEnabled) logger.Debug(message, exception);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DEBUG(this ILog logger, object message)
|
||||
{
|
||||
if (logger.IsDebugEnabled) logger.Debug(message);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DEBUGFORMAT(this ILog logger, string format, params object[] args)
|
||||
{
|
||||
if (logger.IsDebugEnabled) logger.DebugFormat(format, args);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DEBUGFORMAT(this ILog logger, string format, object arg0)
|
||||
{
|
||||
if (logger.IsDebugEnabled) logger.DebugFormat(format, arg0);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DEBUGFORMAT(this ILog logger, string format, object arg0, object arg1)
|
||||
{
|
||||
if (logger.IsDebugEnabled) logger.DebugFormat(format, arg0, arg1);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DEBUGFORMAT(this ILog logger, string format, object arg0, object arg1, object arg2)
|
||||
{
|
||||
if (logger.IsDebugEnabled) logger.DebugFormat(format, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DEBUGFORMAT(this ILog logger, IFormatProvider provider, string format, params object[] args)
|
||||
{
|
||||
if (logger.IsDebugEnabled) logger.DebugFormat(provider, format, args);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="mainForm"></param>
|
||||
/// <param name="configFile">xml log configuration file</param>
|
||||
/// <param name="logFileName">real log file name to be generated.</param>
|
||||
public static void Install(IAppender mainForm, string configFile, string logFileName)
|
||||
{
|
||||
// http://stackoverflow.com/questions/2815940/where-will-log4net-create-this-log-file
|
||||
// see log4netXXXX.xml configuration file
|
||||
var appName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location);
|
||||
log4net.GlobalContext.Properties["LogFileName"] = logFileName.IsNullOrEmpty() ? Path.Combine(CommonUtil.GetProfilePath(), appName) : logFileName;
|
||||
|
||||
if ( File.Exists(configFile) )
|
||||
{
|
||||
log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo(configFile));
|
||||
((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root.AddAppender(mainForm);
|
||||
}
|
||||
else
|
||||
MessageBox.Show(String.Format("Failed to load configuration file {0}.\r\nLog message will not be available.", configFile), appName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 분석 대상 assembly 의 type 을 검사하여, "logger" 라는 이름의 static 멤버를 찾고,
|
||||
/// 사전에 해당 객체를 생성해서 등록해 둔다.
|
||||
/// </summary>
|
||||
/// <param name="mainForm"></param>
|
||||
/// <param name="configFile">e.g "log4net.xml"</param>
|
||||
/// <param name="assemblies">Logger 를 포함하는 분석 대상 assemblies</param>
|
||||
/// <param name="logFileName">logFileName</param>
|
||||
/// <param name="staticLoggerMemberName">e.g "logger"</param>
|
||||
public static void Install(IAppender mainForm, string configFile, IEnumerable<Assembly> assemblies, string logFileName=null, string staticLoggerMemberName = "logger")
|
||||
{
|
||||
Install(mainForm, configFile, logFileName);
|
||||
|
||||
List<Type> types = new List<Type>();
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
foreach (Type t_ in assembly.GetTypes())
|
||||
{
|
||||
Type t = t_.DeclaringType ?? t_;
|
||||
MemberInfo[] mis = t.GetMember(staticLoggerMemberName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
foreach (var mi in mis)
|
||||
{
|
||||
Type candidateType = mi.DeclaringType.DeclaringType ?? mi.DeclaringType;
|
||||
if (!types.Contains(candidateType))
|
||||
{
|
||||
types.Add(candidateType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var type in types)
|
||||
LogProxy.CreateLoggerProxy(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using log4net.Core;
|
||||
using SystemX.Net.Platform.Common.ExtensionMethods;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public class LogEntryManager : IDisposable
|
||||
{
|
||||
private LoggingEvent[] _logEntries;
|
||||
public LoggingEvent[] LogEntries { get { return _logEntries; } }
|
||||
public int Capacity { get { return (int)_capacity; } set { _capacity = (ulong)value; } }
|
||||
private ulong _cursor = 0;
|
||||
private ulong _capacity = 0;
|
||||
|
||||
public int Count { get { return (int)Math.Min(_cursor, (ulong)Capacity); } }
|
||||
public LogEntryManager(int capacity)
|
||||
{
|
||||
Contract.Requires(capacity >= 0);
|
||||
Capacity = Math.Max(capacity, 1000);
|
||||
_logEntries = new LoggingEvent[Capacity];
|
||||
}
|
||||
|
||||
public void AddLogEntry(LoggingEvent logEntry)
|
||||
{
|
||||
_logEntries[_cursor++ % _capacity] = logEntry;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_logEntries = new LoggingEvent[Capacity];
|
||||
_cursor = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// logical index 를 physical index 로 변환해서 반환.
|
||||
/// e.g : capacity=1000, logical=1200 => physical=200
|
||||
/// </summary>
|
||||
/// <param name="n">logical index number</param>
|
||||
/// <returns>physical index number : capacity 적용하여 rolling 한 결과 값</returns>
|
||||
public int LogicalIndex2PhysicalIndex(int n)
|
||||
{
|
||||
Contract.Requires(n.InRange(0, Capacity - 1));
|
||||
|
||||
if (_cursor < _capacity)
|
||||
return n;
|
||||
|
||||
return (int)((_cursor + (ulong)n) % _capacity);
|
||||
}
|
||||
|
||||
public int PhysicalIndex2LogicalIndex(int n)
|
||||
{
|
||||
if (_cursor < _capacity)
|
||||
return n;
|
||||
|
||||
Debug.Assert((ulong)n < _cursor);
|
||||
|
||||
return (int)((ulong)n + (_cursor / _capacity) * _capacity);
|
||||
}
|
||||
|
||||
public LoggingEvent this[int n]
|
||||
{
|
||||
get { return _logEntries[LogicalIndex2PhysicalIndex(n)]; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_logEntries = null;
|
||||
_capacity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
using log4net;
|
||||
using System;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public class LogMessage
|
||||
{
|
||||
public enum LogMessageLevel
|
||||
{
|
||||
NONE = 0,
|
||||
FATAL,
|
||||
DEBUG,
|
||||
INFO,
|
||||
LAST
|
||||
};
|
||||
|
||||
public delegate void MessageEventHandlerOutput(string strMessage, ConsoleColor csColor = ConsoleColor.White, LogMessageLevel logLevel = LogMessageLevel.DEBUG);
|
||||
|
||||
static public class MessageOutput
|
||||
{
|
||||
private static ILog logger => Log4NetWrapper.Logger;
|
||||
static public LogMessageLevel PrintLogLevel { get; set; } = LogMessageLevel.DEBUG;
|
||||
static public MessageEventHandlerOutput UEventOutput;
|
||||
static public void ConsoleWrite(string strMessage, ConsoleColor csColor = ConsoleColor.White, LogMessageLevel logLevel = LogMessageLevel.DEBUG)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (PrintLogLevel >= logLevel)
|
||||
{
|
||||
Console.ForegroundColor = csColor;
|
||||
Console.WriteLine(strMessage);
|
||||
Console.ResetColor();
|
||||
UEventOutput?.Invoke(strMessage, csColor, logLevel);
|
||||
switch (logLevel)
|
||||
{
|
||||
case LogMessageLevel.FATAL:
|
||||
logger.Error(strMessage);
|
||||
|
||||
//WriteEventLogEntry(strMessage);
|
||||
break;
|
||||
case LogMessageLevel.DEBUG:
|
||||
logger.Debug(strMessage);
|
||||
break;
|
||||
default:
|
||||
logger.Info(strMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteEventLogEntry(string message)
|
||||
{
|
||||
// Create an instance of EventLog
|
||||
System.Diagnostics.EventLog eventLog = new System.Diagnostics.EventLog();
|
||||
|
||||
// Check if the event source exists. If not create it.
|
||||
if (!System.Diagnostics.EventLog.SourceExists("CP-ServerX"))
|
||||
{
|
||||
System.Diagnostics.EventLog.CreateEventSource("CP-ServerX", "SystemX");
|
||||
}
|
||||
|
||||
// Set the source name for writing log entries.
|
||||
eventLog.Source = "CP-ServerX";
|
||||
|
||||
// Create an event ID to add to the event log
|
||||
int eventID = 2051;
|
||||
|
||||
// Write an entry to the event log.
|
||||
eventLog.WriteEntry(message,
|
||||
System.Diagnostics.EventLogEntryType.Error,
|
||||
eventID);
|
||||
|
||||
// Close the Event Log
|
||||
eventLog.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using log4net;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// ILog 가 runtime 에 debug log 를 enable/disable 하는 기능을 지원하지 않으므로,
|
||||
/// proxy 를 통해서 enable/disable 한다.
|
||||
/// https://social.msdn.microsoft.com/forums/vstudio/en-US/0624de68-fe7f-45c0-9cd8-468d9dac844b/how-to-disable-log4net-debug-logging-during-runtime
|
||||
/// </summary>
|
||||
public class LogProxy
|
||||
{
|
||||
public ILog Logger { get; set; }
|
||||
public string Name { get { return Logger.Logger.Name; } }
|
||||
|
||||
public Type Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// runtime 에 debug 로그에 대한 enable/disable 여부
|
||||
/// </summary>
|
||||
public bool IsEnableDebug
|
||||
{
|
||||
get { return _isEnableDebug && Logger.IsDebugEnabled; }
|
||||
set
|
||||
{
|
||||
_isEnableDebug = value;
|
||||
Trace.WriteLine($"{Name}: IsEnableDebug={IsEnableDebug}");
|
||||
}
|
||||
}
|
||||
private bool _isEnableDebug = false;
|
||||
|
||||
public bool IsEnableInfo { get { return _isEnableInfo && Logger.IsInfoEnabled; } set { _isEnableInfo = value; } }
|
||||
private bool _isEnableInfo = false;
|
||||
|
||||
public bool IsEnableWarn { get { return _isEnableWarn && Logger.IsWarnEnabled; } set { _isEnableWarn = value; } }
|
||||
private bool _isEnableWarn = false;
|
||||
|
||||
/// <summary>
|
||||
/// 현재 등록된 logger 들 : var loggers = log4net.LogManager.GetCurrentLoggers(); 와 동일
|
||||
/// </summary>
|
||||
public static IEnumerable<LogProxy> CurrentLoggers { get { return _currentLoggers; } }
|
||||
private static List<LogProxy> _currentLoggers = new List<LogProxy>();
|
||||
|
||||
private LogProxy(Type type)
|
||||
{
|
||||
Type = type;
|
||||
Logger = log4net.LogManager.GetLogger(type);
|
||||
}
|
||||
|
||||
public static LogProxy GetLogProxy(Type t)
|
||||
{
|
||||
return CurrentLoggers.FirstOrDefault(l => l.Name == t.FullName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// proxy 된 logger 를 생성한다.
|
||||
/// </summary>
|
||||
/// <param name="t"></param>
|
||||
/// <param name="enableDebug"></param>
|
||||
/// <returns></returns>
|
||||
public static LogProxy CreateLoggerProxy(Type t, bool? enableDebug = null)
|
||||
{
|
||||
var proxy = GetLogProxy(t);
|
||||
if (proxy == null)
|
||||
{
|
||||
proxy = new LogProxy(t);
|
||||
_currentLoggers.Add(proxy);
|
||||
}
|
||||
|
||||
if (enableDebug.HasValue)
|
||||
proxy.IsEnableDebug = enableDebug.Value;
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void Debug(object message, Exception exception)
|
||||
{
|
||||
if (IsEnableDebug) Logger.Debug(message, exception);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void Debug(object message)
|
||||
{
|
||||
if (IsEnableDebug) Logger.Debug(message);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void DebugFormat(string format, params object[] args)
|
||||
{
|
||||
if (IsEnableDebug) Logger.DebugFormat(format, args);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void DebugFormat(string format, object arg0)
|
||||
{
|
||||
if (IsEnableDebug) Logger.DebugFormat(format, arg0);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void DebugFormat(string format, object arg0, object arg1)
|
||||
{
|
||||
if (IsEnableDebug) Logger.DebugFormat(format, arg0, arg1);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void DebugFormat(string format, object arg0, object arg1, object arg2)
|
||||
{
|
||||
if (IsEnableDebug) Logger.DebugFormat(format, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public void DebugFormat(IFormatProvider provider, string format, params object[] args)
|
||||
{
|
||||
if (IsEnableDebug) Logger.DebugFormat(provider, format, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Error(object message) { Logger.Error(message); }
|
||||
public void Error(object message, Exception exception) { Logger.Error(message, exception); }
|
||||
public void ErrorFormat(string format, object arg0) { Logger.ErrorFormat(format, arg0); }
|
||||
public void ErrorFormat(string format, params object[] args) { Logger.ErrorFormat(format, args); }
|
||||
public void ErrorFormat(IFormatProvider provider, string format, params object[] args) { Logger.ErrorFormat(provider, format, args); }
|
||||
public void ErrorFormat(string format, object arg0, object arg1) { Logger.ErrorFormat(format, arg0, arg1); }
|
||||
public void ErrorFormat(string format, object arg0, object arg1, object arg2) { Logger.ErrorFormat(format, arg0, arg1, arg2); }
|
||||
public void Fatal(object message) { Logger.Fatal(message); }
|
||||
public void Fatal(object message, Exception exception) { Logger.Fatal(message, exception); }
|
||||
public void FatalFormat(string format, object arg0) { Logger.FatalFormat(format, arg0); }
|
||||
public void FatalFormat(string format, params object[] args) { Logger.FatalFormat(format, args); }
|
||||
public void FatalFormat(IFormatProvider provider, string format, params object[] args) { Logger.FatalFormat(provider, format, args); }
|
||||
public void FatalFormat(string format, object arg0, object arg1) { Logger.FatalFormat(format, arg0, arg1); }
|
||||
public void FatalFormat(string format, object arg0, object arg1, object arg2) { Logger.FatalFormat(format, arg0, arg1, arg2); }
|
||||
public void Info(object message) { if (IsEnableInfo) Logger.Info(message); }
|
||||
public void Info(object message, Exception exception) { if (IsEnableInfo) Logger.Info(message, exception); }
|
||||
public void InfoFormat(string format, object arg0) { if (IsEnableInfo) Logger.InfoFormat(format, arg0); }
|
||||
public void InfoFormat(string format, params object[] args) { if (IsEnableInfo) Logger.InfoFormat(format, args); }
|
||||
public void InfoFormat(IFormatProvider provider, string format, params object[] args) { if (IsEnableInfo) Logger.InfoFormat(provider, format, args); }
|
||||
public void InfoFormat(string format, object arg0, object arg1) { if (IsEnableInfo) Logger.InfoFormat(format, arg0, arg1); }
|
||||
public void InfoFormat(string format, object arg0, object arg1, object arg2) { if (IsEnableInfo) Logger.InfoFormat(format, arg0, arg1, arg2); }
|
||||
public void Warn(object message) { if (IsEnableWarn) Logger.Warn(message); }
|
||||
public void Warn(object message, Exception exception) { if (IsEnableWarn) Logger.Warn(message, exception); }
|
||||
public void WarnFormat(string format, object arg0) { if (IsEnableWarn) Logger.WarnFormat(format, arg0); }
|
||||
public void WarnFormat(string format, params object[] args) { if (IsEnableWarn) Logger.WarnFormat(format, args); }
|
||||
public void WarnFormat(IFormatProvider provider, string format, params object[] args) { if (IsEnableWarn) Logger.WarnFormat(provider, format, args); }
|
||||
public void WarnFormat(string format, object arg0, object arg1) { if (IsEnableWarn) Logger.WarnFormat(format, arg0, arg1); }
|
||||
public void WarnFormat(string format, object arg0, object arg1, object arg2) { if (IsEnableWarn) Logger.WarnFormat(format, arg0, arg1, arg2); }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using log4net;
|
||||
using log4net.Core;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public class LogRecord
|
||||
{
|
||||
[Browsable(false)]
|
||||
public LoggingEvent LogEntry { get; private set; }
|
||||
[DisplayName("Time")]
|
||||
public string TimeStamp { get { return LogEntry.TimeStamp.ToString("HH:mm:ss.ff"); } }
|
||||
public Level Level { get { return LogEntry.Level; } }
|
||||
[DisplayName("Sender")]
|
||||
public string LoggerName { get { return LogEntry.LoggerName; } }
|
||||
[DisplayName("Message")]
|
||||
public object MessageObject { get { return LogEntry.MessageObject; } }
|
||||
|
||||
[DisplayName("t-Id")]
|
||||
public string ThreadName { get { return LogEntry.ThreadName; } }
|
||||
|
||||
public LogRecord(LoggingEvent log)
|
||||
{
|
||||
LogEntry = log;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append(TimeStamp);
|
||||
sb.Append("\t");
|
||||
sb.Append(Level);
|
||||
sb.Append("\t");
|
||||
sb.Append(LoggerName);
|
||||
sb.Append("\t");
|
||||
sb.Append(MessageObject);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[ComVisible(false)]
|
||||
public class LogRecordFiledWriter<T> : IDisposable
|
||||
{
|
||||
private bool _globalContext;
|
||||
private string _field;
|
||||
private T _valueBackup;
|
||||
|
||||
public LogRecordFiledWriter(string field, T value, bool globalContext=false)
|
||||
{
|
||||
_field = field;
|
||||
_globalContext = globalContext;
|
||||
|
||||
if (globalContext)
|
||||
{
|
||||
var backup = GlobalContext.Properties[field];
|
||||
_valueBackup = backup == null ? default(T) : (T)backup;
|
||||
GlobalContext.Properties[field] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var backup = ThreadContext.Properties[field];
|
||||
_valueBackup = backup == null ? default(T) : (T)backup;
|
||||
ThreadContext.Properties[field] = value;
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
if (_globalContext)
|
||||
GlobalContext.Properties[_field] = _valueBackup;
|
||||
else
|
||||
ThreadContext.Properties[_field] = _valueBackup;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,432 @@
|
||||
//
|
||||
// http://www.mediafire.com/download/fidd3mm85dmq9tb/%281392.03.10%29+Numerical+TextBox+Sample.rar
|
||||
// 이거도 참고로 볼 것... 비슷하지만, 현재 것이 나아보임 http://www.codeproject.com/Articles/30812/Simple-Numeric-TextBox
|
||||
// http://www.thecoolestdolphin.be/?p=38 [Allow only specific characters in textBox in C#]
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class NumericTextBox : TextBox
|
||||
{
|
||||
private bool _negative;
|
||||
private bool _dot;
|
||||
private bool _exponent;
|
||||
private int _decimalNumber;
|
||||
private int _cursorPositionPlus;
|
||||
private char _discriminant;
|
||||
private double _maxValue;
|
||||
private double _minValue;
|
||||
private bool _maxCheck;
|
||||
private bool _minCheck;
|
||||
private string _oldText;
|
||||
|
||||
public NumericTextBox()
|
||||
{
|
||||
_decimalNumber = 4;
|
||||
_negative = true;
|
||||
_dot = true;
|
||||
_exponent = true;
|
||||
_discriminant = ',';
|
||||
_maxValue = 0;
|
||||
_minValue = 0;
|
||||
_maxCheck = false;
|
||||
_minCheck = false;
|
||||
_oldText = string.Empty;
|
||||
|
||||
_balloonTips = new ToolTip()
|
||||
{
|
||||
ToolTipTitle = "Invalid character.",
|
||||
ToolTipIcon = ToolTipIcon.Warning,
|
||||
AutoPopDelay = 0,
|
||||
ShowAlways = false,
|
||||
};
|
||||
}
|
||||
public NumericTextBox(int decimalNumber)
|
||||
: this()
|
||||
{
|
||||
_decimalNumber = decimalNumber;
|
||||
}
|
||||
public NumericTextBox(char discriminant)
|
||||
: this(4)
|
||||
{
|
||||
if (discriminant == '\'' || discriminant == '/' || discriminant == '`')
|
||||
_discriminant = discriminant;
|
||||
else
|
||||
_discriminant = ',';
|
||||
}
|
||||
public NumericTextBox(int decimalNumber, char discriminant)
|
||||
: this(discriminant)
|
||||
{
|
||||
_decimalNumber = decimalNumber;
|
||||
}
|
||||
|
||||
[Description("1000 단위 comma 허용 여부")]
|
||||
public int DecimalNumber
|
||||
{
|
||||
get { return _decimalNumber; }
|
||||
set { _decimalNumber = value; OnTextChanged(new EventArgs()); }
|
||||
}
|
||||
|
||||
[Description("음수 허용 여부")]
|
||||
public bool Negative
|
||||
{
|
||||
get { return _negative; }
|
||||
set { _negative = value; OnTextChanged(new EventArgs()); }
|
||||
}
|
||||
[Description("Period 허용 여부")]
|
||||
public bool Dot
|
||||
{
|
||||
get { return _dot; }
|
||||
set { _dot = value; OnTextChanged(new EventArgs()); }
|
||||
}
|
||||
[Description("Scientific notation 허용 여부")]
|
||||
public bool Exponent
|
||||
{
|
||||
get { return _exponent; }
|
||||
set { _exponent = value; OnTextChanged(new EventArgs()); }
|
||||
}
|
||||
public char Discriminant
|
||||
{
|
||||
get { return _discriminant; }
|
||||
set
|
||||
{
|
||||
if (value == '\'' || value == '/' || value == '`')
|
||||
_discriminant = value;
|
||||
else
|
||||
_discriminant = ',';
|
||||
OnTextChanged(new EventArgs());
|
||||
}
|
||||
}
|
||||
public double MaxValue
|
||||
{
|
||||
get { return _maxValue; }
|
||||
set
|
||||
{
|
||||
_maxValue = (!MinCheck || value >= _minValue) ? value : _maxValue;
|
||||
if (_maxCheck && new NumericalString(this.Text) > _maxValue)
|
||||
this.Text = _maxValue.ToString();
|
||||
}
|
||||
}
|
||||
public double MinValue
|
||||
{
|
||||
get { return _minValue; }
|
||||
set
|
||||
{
|
||||
_minValue = (!MaxCheck || value <= _maxValue) ? value : _minValue;
|
||||
if (_minCheck && new NumericalString(this.Text) < _minValue)
|
||||
this.Text = _minValue.ToString();
|
||||
}
|
||||
}
|
||||
public bool MaxCheck
|
||||
{
|
||||
get { return _maxCheck; }
|
||||
set
|
||||
{
|
||||
_maxCheck = value;
|
||||
if (_maxCheck && new NumericalString(this.Text) > _maxValue)
|
||||
this.Text = _maxValue.ToString();
|
||||
}
|
||||
}
|
||||
public bool MinCheck
|
||||
{
|
||||
get { return _minCheck; }
|
||||
set
|
||||
{
|
||||
_minCheck = value;
|
||||
if (_minCheck && new NumericalString(this.Text) < _minValue)
|
||||
this.Text = _minValue.ToString();
|
||||
}
|
||||
}
|
||||
public NumericalString NumericalText
|
||||
{
|
||||
get { return new NumericalString(this.Text); }
|
||||
}
|
||||
|
||||
|
||||
public double GetDoubleValue()
|
||||
{
|
||||
double value;
|
||||
if (!Double.TryParse(NumericalText.Text, out value))
|
||||
return 0;
|
||||
return value;
|
||||
}
|
||||
public int GetIntValue()
|
||||
{
|
||||
int value;
|
||||
if (!Int32.TryParse(NumericalText.Text, out value))
|
||||
return 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region Baloon Tips
|
||||
[Description("오류 문자 입력시 풍선 도움말 표시 여부")]
|
||||
public bool ShowBalloonTips { get { return _showBalloonTips; } set { _showBalloonTips = value; } }
|
||||
private bool _showBalloonTips = true;
|
||||
private ToolTip _balloonTips;
|
||||
#endregion
|
||||
|
||||
|
||||
protected override void OnTextChanged(EventArgs e)
|
||||
{
|
||||
_balloonTips.Hide(this);
|
||||
_cursorPositionPlus = 0;
|
||||
int SelectionStart = this.SelectionStart;
|
||||
int TextLength = this.Text.Length;
|
||||
int CursorPositionPlus;
|
||||
string Text = NormalTextToNumericString();
|
||||
CursorPositionPlus = _cursorPositionPlus;
|
||||
if ((!_maxCheck || new NumericalString(this.Text) <= _maxValue) && (!_minCheck || new NumericalString(this.Text) >= _minValue))
|
||||
{
|
||||
this.Text = Text;
|
||||
this.SelectionStart = SelectionStart + CursorPositionPlus;
|
||||
_oldText = this.Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Text = _oldText;
|
||||
this.SelectionStart = SelectionStart + _oldText.Length - TextLength;
|
||||
}
|
||||
base.OnTextChanged(e);
|
||||
}
|
||||
protected string NormalTextToNumericString()
|
||||
{
|
||||
string Text = this.Text;
|
||||
string TextTemp1 = string.Empty, TextTemp2 = string.Empty;
|
||||
#region Lowering Characters
|
||||
for (int i = 0; i < Text.Length; i++)
|
||||
TextTemp1 += char.ToLower(Text[i]);
|
||||
#endregion
|
||||
|
||||
|
||||
#region Remove Unknown Characters
|
||||
int FloatNumber = 0;
|
||||
for (int i = 0; i < TextTemp1.Length; i++)
|
||||
if (_negative && TextTemp1[i] == '-' && i == 0)
|
||||
TextTemp2 += TextTemp1[i];
|
||||
else if (TextTemp1[i] == '-' && TextTemp2.IndexOf('e') >= 0 && TextTemp2.Length == TextTemp2.IndexOf('e') + 1)
|
||||
TextTemp2 += TextTemp1[i];
|
||||
else if (char.IsDigit(TextTemp1[i]))
|
||||
{
|
||||
TextTemp2 += TextTemp1[i];
|
||||
if (TextTemp2.IndexOf('.') > -1 && TextTemp2.IndexOf('e') < 0 && i < this.SelectionStart)
|
||||
{
|
||||
FloatNumber++;
|
||||
if (FloatNumber > _decimalNumber && i < this.SelectionStart)
|
||||
_cursorPositionPlus--;
|
||||
}
|
||||
}
|
||||
else if (_dot && _decimalNumber > 0 && TextTemp1[i] == '.' && TextTemp2.IndexOf('.') < 0 && (TextTemp2.IndexOf('e') < 0 || TextTemp2.Length < TextTemp2.IndexOf('e')))
|
||||
TextTemp2 += TextTemp1[i];
|
||||
else if (_exponent && TextTemp1[i] == 'e' && TextTemp2.IndexOf('e') < 0 && TextTemp2.Length >= TextTemp2.IndexOf('.') + 1)
|
||||
TextTemp2 += TextTemp1[i];
|
||||
else if (i < this.SelectionStart)
|
||||
{
|
||||
bool skip = _decimalNumber != 0 && TextTemp1[i] == ',';
|
||||
if ( ! skip && ShowBalloonTips )
|
||||
_balloonTips.Show(String.Format("The character \"{0}\" is invalid.", TextTemp1[i]), this);
|
||||
|
||||
_cursorPositionPlus--;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#region Get Integer Number
|
||||
string INTEGER = string.Empty;
|
||||
int IntegerIndex = (TextTemp2.IndexOf('.') >= 0) ? TextTemp2.IndexOf('.') : (TextTemp2.IndexOf('e') >= 0) ? TextTemp2.IndexOf('e') : TextTemp2.Length;
|
||||
for (int i = 0; i < IntegerIndex; i++)
|
||||
if (char.IsDigit(TextTemp2[i]) || TextTemp2[i] == '-' && INTEGER.IndexOf('-') < 0)
|
||||
INTEGER += TextTemp2[i];
|
||||
#endregion
|
||||
#region Get Float Number
|
||||
string FLOAT = string.Empty;
|
||||
if (TextTemp2.IndexOf('.') >= 0)
|
||||
for (int i = TextTemp2.IndexOf('.') + 1; i < ((TextTemp2.IndexOf('e') >= 0) ? TextTemp2.IndexOf('e') : TextTemp2.Length); i++)
|
||||
if (char.IsDigit(TextTemp2[i]))
|
||||
FLOAT += TextTemp2[i];
|
||||
#endregion
|
||||
#region Put '/' Character in Integer Number
|
||||
string T = string.Empty;
|
||||
int n = 0;
|
||||
for (int i = INTEGER.Length - 1; i >= 0; i--)
|
||||
{
|
||||
T += INTEGER[i];
|
||||
n++;
|
||||
if (n == 3 && i > 0 && INTEGER[i - 1] != '-')
|
||||
{
|
||||
if (i - _cursorPositionPlus < this.SelectionStart)
|
||||
_cursorPositionPlus++;
|
||||
T += _discriminant.ToString();
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
char[] charArray = T.ToCharArray();
|
||||
Array.Reverse(charArray);
|
||||
T = new string(charArray);
|
||||
#endregion
|
||||
#region Put '.' Character
|
||||
if (TextTemp2.IndexOf('.') >= 0)
|
||||
{
|
||||
T += ('.').ToString();
|
||||
for (int i = 0; i < DecimalNumber && i < FLOAT.Length; i++)
|
||||
T += FLOAT[i];
|
||||
}
|
||||
#endregion
|
||||
#region Put 'e' Character
|
||||
if (TextTemp2.IndexOf('e') >= 0)
|
||||
{
|
||||
T += ('e').ToString();
|
||||
for (int i = TextTemp2.IndexOf('e') + 1; i < TextTemp2.Length; i++)
|
||||
T += TextTemp2[i];
|
||||
}
|
||||
#endregion
|
||||
return T;
|
||||
}
|
||||
}
|
||||
public class NumericalString
|
||||
{
|
||||
private string _text;
|
||||
public string Text
|
||||
{
|
||||
get { return _text; }
|
||||
set { _text = value; }
|
||||
}
|
||||
public NumericalString()
|
||||
{
|
||||
_text = string.Empty;
|
||||
}
|
||||
public NumericalString(string Text)
|
||||
{
|
||||
string Temp = string.Empty;
|
||||
for (int i = 0; i < Text.Length; i++)
|
||||
if (char.IsDigit(Text[i]) || Text[i] == '-' || Text[i] == '.' || Text[i] == 'e')
|
||||
Temp += Text[i];
|
||||
_text = Temp;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return (this.Text == string.Empty) ? "0" : this.Text;
|
||||
}
|
||||
public static implicit operator NumericalString(string Text)
|
||||
{
|
||||
return new NumericalString(Text);
|
||||
}
|
||||
public static explicit operator string(NumericalString Text)
|
||||
{
|
||||
return (Text.Text == "") ? "0" : Text.Text;
|
||||
}
|
||||
public static implicit operator double(NumericalString Text)
|
||||
{
|
||||
double value;
|
||||
if (Text.Text == "")
|
||||
return 0;
|
||||
if (Text.Text == "-")
|
||||
return 0;
|
||||
if (Text.Text == "-.")
|
||||
return 0;
|
||||
if (Text.Text.StartsWith("-e"))
|
||||
return 0;
|
||||
if (Text.Text.StartsWith("e"))
|
||||
return 0;
|
||||
if (Text.Text.EndsWith("e") || Text.Text.EndsWith("e-"))
|
||||
return Convert.ToDouble(Text.Text.Substring(0, Text.Text.IndexOf('e')));
|
||||
if (!Double.TryParse(Text.Text, out value))
|
||||
return Convert.ToDouble(Regex.Replace(Text.Text, @"\D", ""));
|
||||
|
||||
return Convert.ToDouble(Text.Text);
|
||||
}
|
||||
public static string operator +(NumericalString Text1, NumericalString Text2)
|
||||
{
|
||||
return Text1.Text + Text2.Text;
|
||||
}
|
||||
public static string operator +(NumericalString Text1, string Text2)
|
||||
{
|
||||
return Text1.Text + Text2;
|
||||
}
|
||||
public static string operator +(NumericalString Text1, char ch)
|
||||
{
|
||||
return Text1.Text + ch.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
public partial class Form1 : Form
|
||||
{
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
numericalTextBox.DecimalNumber = (int)DecimalNumberNumericUpDown.Value;
|
||||
numericalTextBox.Negative = NegativeSignCheckBox.Checked;
|
||||
numericalTextBox.Dot = DotCheckBox.Checked;
|
||||
numericalTextBox.Exponent = ExponentCheckBox.Checked;
|
||||
numericalTextBox.MaxValue = System.Convert.ToDouble(MaximumTextBox.Text);
|
||||
numericalTextBox.MinValue = System.Convert.ToDouble(MinimumTextBox.Text);
|
||||
numericalTextBox.MaxCheck = MaximumCheckBox.Checked;
|
||||
numericalTextBox.MinCheck = MinimumCheckBox.Checked;
|
||||
numericalTextBox.Discriminant = ',';
|
||||
}
|
||||
private void DecimalNumberNumericUpDown_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.DecimalNumber = (int)DecimalNumberNumericUpDown.Value;
|
||||
}
|
||||
private void NegativeSignCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.Negative = NegativeSignCheckBox.Checked;
|
||||
}
|
||||
private void DotCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.Dot = DotCheckBox.Checked;
|
||||
}
|
||||
private void ExponentCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.Exponent = ExponentCheckBox.Checked;
|
||||
}
|
||||
private void MaximumTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.MaxValue = MaximumTextBox.NumericalText;
|
||||
}
|
||||
private void MinimumTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.MinValue = MinimumTextBox.NumericalText;
|
||||
}
|
||||
private void MaximumCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.MaxCheck = MaximumCheckBox.Checked;
|
||||
MaximumTextBox.Enabled = MaximumCheckBox.Checked;
|
||||
}
|
||||
private void MinimumCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
numericalTextBox.MinCheck = MinimumCheckBox.Checked;
|
||||
MinimumTextBox.Enabled = MinimumCheckBox.Checked;
|
||||
}
|
||||
private void GroupSeparatorCharacterTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (GroupSeparatorCharacterTextBox.Text != "" && GroupSeparatorCharacterTextBox.Text.Length == 1)
|
||||
numericalTextBox.Discriminant = System.Convert.ToChar(GroupSeparatorCharacterTextBox.Text);
|
||||
else
|
||||
numericalTextBox.Discriminant = ',';
|
||||
}
|
||||
private void numericalTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
NumericalString NS = "Reza";
|
||||
string s = numericalTextBox.NumericalText.ToString();
|
||||
TextTextBox.Text = (string)numericalTextBox.NumericalText + " Reza";
|
||||
DoubleTextBox.Text = (numericalTextBox.NumericalText + 3).ToString();
|
||||
ConditionTextBox.Text = (numericalTextBox.NumericalText < 100) ? (string)numericalTextBox.NumericalText : "Over 100";
|
||||
}
|
||||
}
|
||||
*/
|
||||
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Rx: System.Reactive.Subjects.Subject 에 대한 base interface
|
||||
/// </summary>
|
||||
[ComVisible(false)]
|
||||
public interface IObservableEvent
|
||||
{
|
||||
}
|
||||
|
||||
public interface IObservableUIEvent : IObservableEvent { }
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public enum SupportedCultures
|
||||
{
|
||||
English,
|
||||
Korean,
|
||||
}
|
||||
|
||||
public static class CultrureConverter
|
||||
{
|
||||
public static string ConvertToString(this SupportedCultures culture)
|
||||
{
|
||||
switch (culture)
|
||||
{
|
||||
case SupportedCultures.English:
|
||||
return "en-US";
|
||||
case SupportedCultures.Korean:
|
||||
return "ko-KR";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CultureInfo ConvertToCultureInfo(this SupportedCultures culture)
|
||||
{
|
||||
return new CultureInfo(culture.ConvertToString());
|
||||
}
|
||||
|
||||
public static void Apply(this SupportedCultures culture)
|
||||
{
|
||||
var ci = culture.ConvertToCultureInfo();
|
||||
ci.Apply();
|
||||
}
|
||||
|
||||
public static void Apply(this CultureInfo ci)
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = ci;
|
||||
Thread.CurrentThread.CurrentUICulture = ci;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public class CwdChanger : IDisposable
|
||||
{
|
||||
protected string m_strBackupDirectory = null;
|
||||
|
||||
public CwdChanger() : this(null) { }
|
||||
public CwdChanger(string strTargetDirectory/*=null*/)
|
||||
{
|
||||
m_strBackupDirectory = Directory.GetCurrentDirectory();
|
||||
if (!String.IsNullOrEmpty(strTargetDirectory))
|
||||
Directory.SetCurrentDirectory(strTargetDirectory);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Directory.SetCurrentDirectory(m_strBackupDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.Util
|
||||
{
|
||||
public static class XMLControl
|
||||
{
|
||||
public static XDocument OpenXMLDocument(string strXmlPath)
|
||||
{
|
||||
XDocument xDoc = XDocument.Load(strXmlPath);
|
||||
|
||||
return xDoc;
|
||||
}
|
||||
|
||||
public static XElement OpenXMLDocument(string strXmlPath, string strRootElemName)
|
||||
{
|
||||
XDocument xDoc = XDocument.Load(strXmlPath);
|
||||
|
||||
var xElement = xDoc.Element(strRootElemName);
|
||||
|
||||
if (xElement == null) return null;
|
||||
|
||||
return xElement;
|
||||
}
|
||||
|
||||
public static XElement OpenXMLElement(XElement xRootElem, string strChildName)
|
||||
{
|
||||
var xElement = xRootElem.Element(strChildName);
|
||||
|
||||
if (xElement == null) return null;
|
||||
|
||||
return xElement;
|
||||
}
|
||||
|
||||
public static void LoadXMLAttributes(object objOwner, Type typAttributes, XElement xelem)
|
||||
{
|
||||
foreach (string strAttrb in Enum.GetNames(typAttributes))
|
||||
{
|
||||
string strData = xelem.Attribute(strAttrb).Value;
|
||||
|
||||
PropertyInfo propInfo = CommonUtil.GetProperty(objOwner, strAttrb);
|
||||
|
||||
if (propInfo.PropertyType == typeof(int))
|
||||
CommonUtil.SetPropertyValue(objOwner, strAttrb, Convert.ToInt32(strData));
|
||||
else if (propInfo.PropertyType == typeof(string))
|
||||
CommonUtil.SetPropertyValue(objOwner, strAttrb, strData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user