C# 서비스 등록

이동근·2026년 3월 13일

C#

목록 보기
7/9

Window 서비스

  • Window 서비스 : 백그라운드에서 진행되는 프로그램

    • 사용자가 직접 실행하지 않아도 윈도우가 부팅될 때 자동으로 시작되어 시스템 기능을 지원

    • 관리도구 : Win + R 키를 누르고 service.msc를 입력하여 실행되는 서비스 창에서 시작, 중지, 다시 시작 등 변경이 가능

C#에서 서비스 만들기

  • C# version : 4.8(.NET Framework)

  • 솔루션 탐색기에 서비스 프로젝트가 생성됨

  • Service1.cs에서 [디자인]에서 왼쪽 밑에 설치 관리자 추가를 클릭하여

    • projectInstaller.cs 생성 → serviceInstaller1, serviceProcessInstaller1이 존재함

      • serviceInstaller1 : 서비스명, 설명 등 설정 가능

      • serviceProcessInstaller1 : 서비스가 실행될 계정(Account)을 설정 가능

  • Service1.cs의 코드에서 OnStart() , OnStop() 메서드를 이용하여 서비스를 실행, 중지 시킴

Service 예제

  • 예제 : Service를 등록하여 설정된 경로에 설정된 파일(메모장)에 3초마다 현재시간을 기록하도록 작성

실행 순서

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 폴더 생성 후 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.xml에 설정값을 읽어야하는 경우

    • 단 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);

ServiceWorker 설정

  • 실제로 서비스 작업을 처리하는 클래스

  • 프로젝트 안에 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();
        }
    }
}
profile
안녕하세요

0개의 댓글