Window 서비스 : 백그라운드에서 진행되는 프로그램
사용자가 직접 실행하지 않아도 윈도우가 부팅될 때 자동으로 시작되어 시스템 기능을 지원
관리도구 : Win + R 키를 누르고 service.msc를 입력하여 실행되는 서비스 창에서 시작, 중지, 다시 시작 등 변경이 가능




Service1.cs에서 [디자인]에서 왼쪽 밑에 설치 관리자 추가를 클릭하여
projectInstaller.cs 생성 → serviceInstaller1, serviceProcessInstaller1이 존재함
serviceInstaller1 : 서비스명, 설명 등 설정 가능
serviceProcessInstaller1 : 서비스가 실행될 계정(Account)을 설정 가능
Service1.cs의 코드에서 OnStart() , OnStop() 메서드를 이용하여 서비스를 실행, 중지 시킴
실행 순서
1. 서비스 프로젝트 생성 2. Service.cs에 서비스에서 실행할 코드 작성 3. 설치관리자 추가 → serviceInstaller, serviceProcessInstaller을 생성 4. 서비스명, 설명 등 설정 5. 디버깅할 로그 기록 코드까지 작성 → 서비스는 디버깅이 어려워서 로그기록으로 확인 6. 빌드하여 .exe파일 생성 7. 빌드 후 cmd을 이용하여 서비스 등록 8. 서비스 등록 후 실행 9. 서비스 정지 10. 서비스 종료
Service 예제 코드
using System.ServiceProcess; using WindowsService1.Modules; namespace WindowsService1 { public partial class Service1 : ServiceBase { private ServiceWorker _worker = null; public Service1() { InitializeComponent(); } protected override void OnStart(string[] args) { ServiceStart(); } protected override void OnStop() { ServiceStop(); } private void ServiceStart() { if (_worker == null) { _worker = new ServiceWorker(); _worker.Start(); } } private void ServiceStop() { if (_worker != null) { _worker.Stop(); _worker.Dispose(); _worker = null; } } } }
cmd를 관리자 권한으로 실행 예시
:: 1. cmd 관리자 권한으로 실행 후 InstallUtil.exe 경로로 이동 cd C:\Windows\Microsoft.NET\Framework\v4.0.30319\ :: 2. 서비스 설치 (프로젝트 실행파일 경로 입력) InstallUtil.exe C:\MyProject\bin\Release\MyService.exe :: 3. 서비스 시작 sc start ServiceName :: [services.msc 확인] 해당 서비스 상태가 "실행 중" 으로 바뀌는지 확인 :: 4. 서비스 상태 확인 sc query ServiceName :: [services.msc 확인] 해당 서비스 찾아서 상태(Status) 컬럼 확인 :: 5. 서비스 중지 sc stop ServiceName :: [services.msc 확인] 해당 서비스 상태가 "중지됨" 으로 바뀌는지 확인 :: 6. 서비스 삭제 sc delete ServiceName :: [services.msc 확인] 해당 서비스가 목록에서 사라지는지 확인 :: (바로 안 사라질 수 있음 → 새로고침 or 재시작 후 확인)
Config 폴더 생성 후 Config.xml을 생성Config.xml 예시
<?xml version="1.0" encoding="utf-8" ?> <CONFIG> <APP> <NAME>MyApplication</NAME> <VERSION>1.0.0</VERSION> <LANGUAGE>ko-KR</LANGUAGE> </APP> <SERVER> <HOST>localhost</HOST> <PORT>8080</PORT> </SERVER> <DATABASE> <DATASOURCE>127.0.0.1</DATASOURCE> <CATALOG>TestDB</CATALOG> <USER_ID>admin</USER_ID> <USER_PWD>1234</USER_PWD> <TIMEOUT>30</TIMEOUT> </DATABASE> <LOG> <PATH>C:\Logs\</PATH> <LEVEL>DEBUG</LEVEL> </LOG> </CONFIG>
Config.xml에 설정값을 읽어야하는 경우
Config 클래스가 존재해야함이메일로 예시
// 현재 서비스와 전혀 관련이 없는 예시임을 인식바람 // 1. 경로 설정 (Config.xml에서 읽어옴) string xmlFilePath = $@"{Application.StartupPath}\Config\Config.xml"; string smtpAddress = Config.Instance.Email.Settings[0].Address; int smtpPort = Config.Instance.Email.Settings[0].Port; string sender = Config.Instance.Email.Settings[0].Sender; // 2. 직렬화 데이터 (보낼 데이터를 JSON으로 변환) EmailData emailData = new EmailData() { Title = "테스트 메일", Content = "안녕하세요", Receiver = "test@test.com" }; string data = JsonConvert.SerializeObject(emailData); // 3. 데이터 담아서 사용 (이메일 전송) EmailSender emailSender = new EmailSender(smtpAddress, smtpPort, sender); await emailSender.SendAsync(data);
실제로 서비스 작업을 처리하는 클래스
프로젝트 안에 Modules 폴더 안에 ServiceWorker.cs 클래스 생성
ServiceWorker 예시
using System; using System.IO; using System.Timers; namespace WindowsService1.Modules { public class ServiceWorker : IDisposable { private Timer timer; private const string folderPath = "D:\\test"; private const string filePath = folderPath + "\\service.txt"; StreamWriter sw; #region "서비스 시작" public void Start() { if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); writeLog("Service Onstart"); } timer = new Timer(); timer.Interval = 3000; // 3s 마다 실행 timer.Elapsed += Timer_Elapsed; timer.Start(); } #endregion #region "서비스 종료" public void Stop() { writeLog("Service OnStop"); } #endregion #region "로그 기록 " // 사용 예시 // WriteLog("발행 완료"); private void writeLog(string message) { try { if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); string log = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}"; File.AppendAllText(filePath, log + Environment.NewLine); } catch { } // 로그 실패는 무시 } #endregion #region "Timer 이벤트" private void Timer_Elapsed(object sender, ElapsedEventArgs e) { sw = new StreamWriter(filePath, true); sw.WriteLine(DateTime.Now.ToString()); sw.Close(); } #endregion public void Dispose() { throw new NotImplementedException(); } } }