728x90
반응형
728x170
[TestLibrary 프로젝트]
▶ ILogHelper.cs
using System;
namespace TestLibrary
{
/// <summary>
/// 로그 헬퍼 인터페이스
/// </summary>
public interface ILogHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
#region 메시지 쓰기 - WriteMessage(message)
/// <summary>
/// 메시지 쓰기
/// </summary>
/// <param name="message">메시지</param>
void WriteMessage(string message);
#endregion
#region 로그 쓰기 - WriteLog(format, parameterArray)
/// <summary>
/// 로그 쓰기
/// </summary>
/// <param name="format">포맷 문자열</param>
/// <param name="parameterArray">매개 변수 배열</param>
void WriteLog(string format, params object[] parameterArray);
#endregion
#region 에러 로그 쓰기 - WriteErrorLog(exception, caption)
/// <summary>
/// 에러 로그 쓰기
/// </summary>
/// <param name="exception">예외</param>
/// <param name="caption">제목 문자열</param>
void WriteErrorLog(Exception exception, string caption);
#endregion
#region 에러 로그 쓰기 - WriteErrorLog(exception, caption)
/// <summary>
/// 에러 로그 쓰기
/// </summary>
/// <param name="message">예외 메시지</param>
/// <param name="caption">제목 문자열</param>
void WriteErrorLog(string message, string caption);
#endregion
#region 덤프 로그 쓰기 - WriteDumpLog(sourceObject, caption)
/// <summary>
/// 덤프 로그 쓰기
/// </summary>
/// <param name="sourceObject">예외</param>
/// <param name="caption">제목 문자열</param>
void WriteDumpLog(object sourceObject, string caption);
#endregion
}
}
728x90
▶ FileLogHelper.cs
using System;
using System.IO;
namespace TestLibrary
{
/// <summary>
/// 파일 로그 헬퍼
/// </summary>
public class FileLogHelper : ILogHelper
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 동기 객체
/// </summary>
private object syncObject;
/// <summary>
/// 로그 루트 디렉토리 경로
/// </summary>
private string logRootDirectoryPath;
/// <summary>
/// 파일명
/// </summary>
private string fileName;
/// <summary>
/// 파일 경로
/// </summary>
private string filePath;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - FileLogHelper(logRootDirectoryPath, fileName)
/// <summary>
/// 생성자
/// </summary>
/// <param name="logRootDirectoryPath">로그 루트 디렉토리 경로</param>
/// <param name="fileName">파일명</param>
public FileLogHelper(string logRootDirectoryPath, string fileName)
{
this.syncObject = new object();
this.logRootDirectoryPath = logRootDirectoryPath;
this.fileName = fileName;
this.filePath = Path.Combine(this.logRootDirectoryPath, this.fileName);
if(!Directory.Exists(this.logRootDirectoryPath))
{
Directory.CreateDirectory(this.logRootDirectoryPath);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 메시지 쓰기 - WriteMessage(message)
/// <summary>
/// 메시지 쓰기
/// </summary>
/// <param name="message">메시지</param>
public void WriteMessage(string message)
{
lock(this.syncObject)
{
using(StreamWriter writer = File.AppendText(this.filePath))
{
writer.WriteLine(message);
}
}
}
#endregion
#region 로그 쓰기 - WriteLog(format, parameterArray)
/// <summary>
/// 로그 쓰기
/// </summary>
/// <param name="format">포맷 문자열</param>
/// <param name="parameterArray">매개 변수 배열</param>
public void WriteLog(string format, params object[] parameterArray)
{
string message;
if(parameterArray.Length == 0)
{
message = format;
}
else
{
message = string.Format(format, parameterArray);
}
string log = string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss"), message);
WriteMessage(log);
}
#endregion
#region 에러 로그 쓰기 - WriteErrorLog(exception, source)
/// <summary>
/// 에러 로그 쓰기
/// </summary>
/// <param name="exception">예외</param>
/// <param name="source">소스 문자열</param>
public void WriteErrorLog(Exception exception, string source)
{
lock(this.syncObject)
{
string title = string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss"), source);
using(StreamWriter writer = File.AppendText(this.filePath))
{
writer.WriteLine(title);
writer.WriteLine("--------------------------------------------------");
writer.WriteLine(exception.ToString());
writer.WriteLine("--------------------------------------------------");
}
}
}
#endregion
#region 에러 로그 쓰기 - WriteErrorLog(message, source)
/// <summary>
/// 에러 로그 쓰기
/// </summary>
/// <param name="message">예외 메시지</param>
/// <param name="source">소스 문자열</param>
public void WriteErrorLog(string message, string source)
{
lock (this.syncObject)
{
string title = string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss"), source);
using (StreamWriter writer = File.AppendText(this.filePath))
{
writer.WriteLine(title);
writer.WriteLine("--------------------------------------------------");
writer.WriteLine(message);
writer.WriteLine("--------------------------------------------------");
}
}
}
#endregion
#region 덤프 로그 쓰기 - WriteDumpLog(sourceObject, caption)
/// <summary>
/// 덤프 로그 쓰기
/// </summary>
/// <param name="sourceObject">예외</param>
/// <param name="caption">제목 문자열</param>
public void WriteDumpLog(object sourceObject, string caption)
{
lock(this.syncObject)
{
string title = string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss"), caption);
using(StreamWriter writer = File.AppendText(this.filePath))
{
writer.WriteLine(title);
writer.WriteLine("--------------------------------------------------");
writer.WriteLine(sourceObject.ToString());
writer.WriteLine("--------------------------------------------------");
}
}
}
#endregion
}
}
300x250
▶ RepeatWorker.cs
using System;
using System.Threading;
namespace TestLibrary
{
/// <summary>
/// 반복 작업자
/// </summary>
public class RepeatWorker : IDisposable
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region Field
/// <summary>
/// 로그 헬퍼
/// </summary>
protected ILogHelper logHelper = null;
/// <summary>
/// 스레드
/// </summary>
protected Thread thread = null;
/// <summary>
/// 루프 계속 여부
/// </summary>
protected bool continueLoop = true;
/// <summary>
/// 휴지 여부
/// </summary>
protected bool isSleep = false;
/// <summary>
/// 휴지 시간 (단위 : 밀리초)
/// </summary>
protected int sleepTime;
/// <summary>
/// 작업 액션
/// </summary>
protected Action<object> workAction;
/// <summary>
/// 작업 매개 변수
/// </summary>
protected object workParameter;
/// <summary>
/// 실행 여부
/// </summary>
protected bool isRunning = false;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 로그 헬퍼 - LogHelper
/// <summary>
/// 로그 헬퍼
/// </summary>
public ILogHelper LogHelper
{
get
{
return this.logHelper;
}
set
{
this.logHelper = value;
}
}
#endregion
#region 스레드 - Thread
/// <summary>
/// 스레드
/// </summary>
public Thread Thread
{
get
{
return this.thread;
}
}
#endregion
#region 휴지 시간 (단위 : 밀리초) - SleepTime
/// <summary>
/// 휴지 시간 (단위 : 밀리초)
/// </summary>
public int SleepTime
{
get
{
return this.sleepTime;
}
set
{
this.sleepTime = value;
}
}
#endregion
#region 작업 액션 - WorkAction
/// <summary>
/// 작업 액션
/// </summary>
public Action<object> WorkAction
{
get
{
return this.workAction;
}
set
{
this.workAction = value;
}
}
#endregion
#region 작업 매개 변수 - WorkParameter
/// <summary>
/// 작업 매개 변수
/// </summary>
public object WorkParameter
{
get
{
return this.workParameter;
}
set
{
this.workParameter = value;
}
}
#endregion
#region 실행 여부 - IsRunning
/// <summary>
/// 실행 여부
/// </summary>
public bool IsRunning
{
get
{
return this.isRunning;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - RepeatWorker(workAction, workParameter, sleepTime)
/// <summary>
/// 생성자
/// </summary>
/// <param name="workAction">작업 액션</param>
/// <param name="workParameter">작업 매개 변수</param>
/// <param name="sleepTime">휴지 시간 (단위 : 밀리초(</param>
public RepeatWorker(Action<object> workAction, object workParameter, int sleepTime = 1000)
{
this.workAction = workAction;
this.workParameter = workParameter;
this.sleepTime = sleepTime;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 시작하기 - Start()
/// <summary>
/// 시작하기
/// </summary>
public void Start()
{
try
{
if(this.isRunning)
{
return;
}
this.isRunning = true;
#region 스레드를 설정한다.
if(this.thread != null)
{
if(this.thread.IsAlive)
{
this.thread.Abort();
}
this.thread = null;
}
this.thread = new Thread(new ThreadStart(ProcessThread));
this.thread.IsBackground = true;
#endregion
this.thread.Start();
}
catch(Exception exception)
{
this.isRunning = false;
this.logHelper?.WriteErrorLog(exception, "ERROR START FUNCTION");
throw exception;
}
}
#endregion
#region 중단하기 - Stop()
/// <summary>
/// 중단하기
/// </summary>
public void Stop()
{
try
{
if(!this.isRunning)
{
return;
}
this.isRunning = false;
#region 스레드를 중단한다.
this.continueLoop = false;
Thread.Sleep(500);
if(this.thread != null && this.thread.IsAlive)
{
if(this.isSleep)
{
this.thread.Abort();
}
}
#endregion
}
catch(Exception exception)
{
this.logHelper?.WriteErrorLog(exception, "ERROR STOP FUNCTION");
}
}
#endregion
#region 리소스 해제하기 - Dispose()
/// <summary>
/// 리소스 해제하기
/// </summary>
public void Dispose()
{
Stop();
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 스레드 처리하기 - ProcessThread()
/// <summary>
/// 스레드 처리하기
/// </summary>
private void ProcessThread()
{
while(this.continueLoop)
{
try
{
this.workAction?.Invoke(this.workParameter);
}
catch(Exception exception)
{
this.logHelper?.WriteErrorLog(exception, "ERROR WHEN PROCESS THREAD");
}
if(!this.continueLoop)
{
break;
}
this.isSleep = true;
Thread.Sleep(this.sleepTime);
this.isSleep = false;
}
}
#endregion
}
}
▶ TestNode.cs
using System;
namespace TestLibrary
{
/// <summary>
/// 테스트 노드
/// </summary>
public class TestNode
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
#region 로그
/// <summary>
/// 로그 헬퍼
/// </summary>
private ILogHelper logHelper;
#endregion
#region 실행 작업자
/// <summary>
/// 실행 작업자 주기 (단위 : 밀리초)
/// </summary>
private int executeWorkerInterval = 1000; // 0.1초
/// <summary>
/// 실행 작업자
/// </summary>
private RepeatWorker executeWorker = null;
#endregion
/// <summary>
/// 실행 여부
/// </summary>
private bool isRunning = false;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 실행 여부 - IsRunning
/// <summary>
/// 실행 여부
/// </summary>
public bool IsRunning
{
get
{
return this.isRunning;
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - TestNode()
/// <summary>
/// 생성자
/// </summary>
public TestNode()
{
#region 로그 헬퍼를 설정한다.
this.logHelper = new FileLogHelper("d:\\", "TestNode.log");
#endregion
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 시작하기 - Start()
/// <summary>
/// 시작하기
/// </summary>
public void Start()
{
try
{
this.logHelper?.WriteLog("BEGIN START FUNCTION");
if(this.isRunning)
{
this.logHelper?.WriteLog("STOP START FUNCTION : AlreadyRunning");
return;
}
this.isRunning = true;
#region 실행 작업자를 설정한다.
if(this.executeWorker != null)
{
if(this.executeWorker.IsRunning)
{
this.executeWorker.Stop();
}
this.executeWorker = null;
}
this.executeWorker = new RepeatWorker(new Action<object>(ProcessExecute), null, this.executeWorkerInterval);
#endregion
this.executeWorker.Start();
this.logHelper?.WriteLog("END START FUNCTION");
}
catch(Exception exception)
{
this.isRunning = false;
this.logHelper?.WriteErrorLog(exception, "ERROR START FUNCTION");
throw exception;
}
}
#endregion
#region 중단하기 - Stop()
/// <summary>
/// 중단하기
/// </summary>
public void Stop()
{
try
{
this.logHelper?.WriteLog("BEGIN STOP FUNCTION");
if(!this.isRunning)
{
this.logHelper?.WriteLog("STOP STOP FUNCTION : AlreadyStopped");
return;
}
this.isRunning = false;
#region 실행 작업자를 중단한다.
this.executeWorker.Stop();
this.executeWorker = null;
#endregion
this.logHelper?.WriteLog("END STOP FUNCTION");
}
catch(Exception exception)
{
this.isRunning = false;
this.logHelper?.WriteErrorLog(exception, "ERROR STOP FUNCTION");
}
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 실행 처리하기 - ProcessExecute(parameter)
/// <summary>
/// 실행 처리하기
/// </summary>
/// <param name="parameter">매개 변수</param>
private void ProcessExecute(object parameter)
{
try
{
this.logHelper?.WriteLog("테스트 메시지");
}
catch(Exception exception)
{
this.logHelper?.WriteErrorLog(exception, "ERROR PROCESS EXECUTE FUNCTION");
}
}
#endregion
}
}
[TestService 프로젝트]
▶ ProjectInstaller.cs
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace TestService
{
/// <summary>
/// 프로젝트 설치자
/// </summary>
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 서비스 프로세스 설치자
/// </summary>
private ServiceProcessInstaller serviceProcessInstaller;
/// <summary>
/// 서비스 설치자
/// </summary>
private ServiceInstaller serviceInstaller;
/// <summary>
/// 서비스명
/// </summary>
private const string SERVICE_NAME = "TestNode";
/// <summary>
/// 서비스 설명
/// </summary>
private const string SERVICE_DESCRIPTION = "테스트 노드";
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - ProjectInstaller()
/// <summary>
/// 생성자
/// </summary>
public ProjectInstaller()
{
this.serviceProcessInstaller = new ServiceProcessInstaller();
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
serviceProcessInstaller.Password = null;
serviceProcessInstaller.Username = null;
this.serviceInstaller = new ServiceInstaller();
serviceInstaller.ServiceName = SERVICE_NAME;
serviceInstaller.DisplayName = SERVICE_NAME;
serviceInstaller.Description = SERVICE_DESCRIPTION;
serviceInstaller.StartType = ServiceStartMode.Automatic;
Installers.AddRange(new Installer[] { this.serviceProcessInstaller, this.serviceInstaller });
}
#endregion
}
}
▶ ProjectService.cs
using System;
using System.ServiceProcess;
using TestLibrary;
namespace TestService
{
/// <summary>
/// 프로젝트 서비스
/// </summary>
public partial class ProjectService : ServiceBase
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 에이전트 노드
/// </summary>
private TestNode testNode;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - ProjectService()
/// <summary>
/// 생성자
/// </summary>
public ProjectService()
{
this.testNode = new TestNode();
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 테스트 하기 - Test(argumentArray)
/// <summary>
/// 테스트 하기
/// </summary>
/// <param name="argumentArray">인자 배열</param>
public void Test(string[] argumentArray)
{
OnStart(argumentArray);
Console.ReadKey(true);
OnStop();
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Protected
#region 시작시 처리하기 - OnStart(argumentArray)
/// <summary>
/// 시작시 처리하기
/// </summary>
/// <param name="argumentArray">인자 배열</param>
protected override void OnStart(string[] argumentArray)
{
this.testNode.Start();
}
#endregion
#region 중단시 처리하기 - OnStop()
/// <summary>
/// 중단시 처리하기
/// </summary>
protected override void OnStop()
{
this.testNode.Stop();
}
#endregion
}
}
▶ Program.cs
using System;
using System.ServiceProcess;
namespace TestService
{
/// <summary>
/// 프로그램
/// </summary>
static class Program
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Static
//////////////////////////////////////////////////////////////////////////////// Private
#region 프로그램 시작하기 - Main(argumentArray)
/// <summary>
/// 프로그램 시작하기
/// </summary>
/// <param name="argumentArray">인자 배열</param>
private static void Main(string[] argumentArray)
{
if(Environment.UserInteractive)
{
ProjectService service = new ProjectService();
service.Test(argumentArray);
}
else
{
ServiceBase[] serviceBaseArray;
serviceBaseArray = new ServiceBase[] { new ProjectService() };
ServiceBase.Run(serviceBaseArray);
}
}
#endregion
}
}
728x90
반응형
그리드형(광고전용)
'C# > Common' 카테고리의 다른 글
[C#/COMMON] 포터블 실행 파일(Portable Executable File) 만들기 (0) | 2021.01.14 |
---|---|
[C#/COMMON] Process 클래스 : 프로세스 파일 경로 리스트 구하기 (0) | 2021.01.13 |
[C#/COMMON] ManagementObjectSearcher 클래스 : 플러그 앤 플레이 장치 조회하기 (0) | 2021.01.13 |
[C#/COMMON] List<T> 클래스 : ForEach 메소드 사용하기 (0) | 2021.01.10 |
[C#/COMMON] XML 주석 개행하기 (0) | 2021.01.09 |
[C#/COMMON] 윈도우즈 서비스 사용하기 (0) | 2021.01.02 |
[C#/COMMON] 문자열에서 IP 주소로 변환하기 (0) | 2021.01.01 |
[C#/COMMON] WebClient 클래스 : OpenRead 메소드를 사용해 인터넷 연결 여부 구하기 (0) | 2021.01.01 |
[C#/COMMON] 사운드 파일 재생하기 (0) | 2020.12.28 |
[C#/COMMON] 윈도우즈 화면 잠금 여부 구하기/화면 보호기 실행 여부 구하기 (0) | 2020.12.27 |
[C#/COMMON] DLL Injection 사용하기 (0) | 2020.12.25 |
댓글을 달아 주세요