자습서: Windows 서비스 앱 만들기

경고

이 설명서는 최신 버전의 Windows Service를 위한 것이 아닙니다. BackgroundService 및 Worker Service 템플릿을 사용하는 Windows Services의 최신 콘텐츠는 다음을 참조하세요.

이 문서에서는 이벤트 로그에 메시지를 쓰는 Windows 서비스 앱을 Visual Studio에서 만드는 방법을 보여 줍니다.

서비스 만들기

우선 프로젝트를 만들고 서비스가 제대로 작동하는 데 필요한 값을 설정합니다.

  1. Visual Studio 파일 메뉴에서 새로 만들기>프로젝트를 선택하거나 Ctrl+Shift+N을 눌러 새 프로젝트 창을 엽니다.

  2. Windows 서비스(.NET Framework) 프로젝트 템플릿을 찾아 선택합니다.

    참고

    Windows 서비스 템플릿이 표시되지 않는 경우 Visual Studio 설치 관리자를 사용하여 .NET 데스크톱 개발 워크로드를 설치해야 할 수 있습니다.

  3. 이름에서 MyNewService를 입력한 다음, 확인을 선택합니다.

    디자인 탭이 표시됩니다(Service1.cs [디자인] 또는 Service1.vb [디자인] ).

    프로젝트 템플릿은 System.ServiceProcess.ServiceBase에서 상속된 Service1이라는 구성 요소 클래스를 포함합니다. 여기에는 서비스를 시작하는 코드 등의 많은 기본 서비스 코드가 포함됩니다.

서비스 이름 바꾸기

서비스 이름을 Service1에서 MyNewService로 바꿉니다.

  1. 솔루션 탐색기에서 Service1.cs 또는 Service1.vb를 선택하고 바로 가기 메뉴에서 이름 바꾸기를 선택합니다. 파일 이름을 MyNewService.cs 또는 MyNewService.vb로 바꾼 다음, Enter 키를 누릅니다.

    코드 요소 Service1에 대한 모든 참조 이름을 변경할지 여부를 묻는 팝업 창이 나타납니다.

  2. 팝업 창에서 를 선택합니다.

    이름 바꾸기 프롬프트

  3. 디자인 탭의 바로 가기 메뉴에서 속성을 선택합니다. 속성 창에서 ServiceName 값을 MyNewService로 변경합니다.

    서비스 속성

  4. 파일 메뉴에서 모두 저장을 선택합니다.

서비스에 기능 추가

다음 섹션에서는 Windows 서비스에 사용자 지정 이벤트 로그를 추가합니다. Windows 서비스에 추가할 수 있는 구성 요소 종류의 한 예로 EventLog 구성 요소를 사용합니다.

사용자 지정 이벤트 로그 기능 추가

  1. 솔루션 탐색기에서 MyNewService.cs 또는 MyNewService.vb의 바로 가기 메뉴에 있는 뷰 디자이너를 선택합니다.

  2. 도구 상자에서 구성 요소를 확장한 다음, EventLog 구성 요소를 Service1.cs [디자인] 또는 Service1.vb [디자인] 탭으로 끕니다.

  3. 솔루션 탐색기에서 MyNewService.cs 또는 MyNewService.vb의 바로 가기 메뉴에 있는 코드 보기를 선택합니다.

  4. 사용자 지정 이벤트 로그를 정의합니다.

    C#의 경우 다음 코드 조각과 같이 기존 MyNewService() 생성자를 편집합니다. Visual Basic의 경우 다음 코드 조각과 같이 New() 생성자를 추가합니다.

    public MyNewService()
    {
        InitializeComponent();
        eventLog1 = new System.Diagnostics.EventLog();
        if (!System.Diagnostics.EventLog.SourceExists("MySource"))
        {
            System.Diagnostics.EventLog.CreateEventSource(
                "MySource","MyNewLog");
        }
        eventLog1.Source = "MySource";
        eventLog1.Log = "MyNewLog";
    }
    
    ' To access the constructor in Visual Basic, select New from the
    ' method name drop-down list. 
    Public Sub New()
        MyBase.New()
        InitializeComponent()
        Me.EventLog1 = New System.Diagnostics.EventLog
        If Not System.Diagnostics.EventLog.SourceExists("MySource") Then
            System.Diagnostics.EventLog.CreateEventSource("MySource",
            "MyNewLog")
        End If
        EventLog1.Source = "MySource"
        EventLog1.Log = "MyNewLog"
    End Sub
    
  5. using 문을 MyNewService.cs에 추가하거나(없는 경우) System.Diagnostics 네임스페이스에 대해서는 Imports 문을 MyNewService.vb에 추가합니다.

    using System.Diagnostics;
    
    Imports System.Diagnostics
    
  6. 파일 메뉴에서 모두 저장을 선택합니다.

서비스가 시작될 때 수행되는 동작 정의

MyNewService.cs 또는 MyNewService.vb에 대한 코드 편집기에서 OnStart 메서드를 찾습니다. 프로젝트를 만들 때 Visual Studio에서 빈 메서드 정의를 자동으로 만들었습니다. 서비스가 시작될 때 이벤트 로그에 항목을 기록하는 코드를 추가합니다.

protected override void OnStart(string[] args)
{
    eventLog1.WriteEntry("In OnStart.");
}
' To access the OnStart in Visual Basic, select OnStart from the
' method name drop-down list. 
Protected Overrides Sub OnStart(ByVal args() As String)
    EventLog1.WriteEntry("In OnStart")
End Sub

폴링

서비스 애플리케이션은 오랫동안 실행되도록 설계되므로 대개 OnStart 메서드에서 설정한 시스템을 폴링하거나 모니터링합니다. 서비스의 작업이 시작되고 나면 OnStart 메서드가 운영 체제에 반환되어야 시스템이 차단되지 않습니다.

간단한 폴링 메커니즘을 설정하려면 System.Timers.Timer 구성 요소를 사용합니다. 타이머가 일정 간격으로 Elapsed 이벤트를 발생시키며 서비스는 이벤트가 발생했을 때 모니터링을 수행할 수 있습니다. Timer 구성 요소는 다음과 같이 사용합니다.

  • MyNewService.OnStart 메서드에서 Timer 구성 요소의 속성을 설정합니다.
  • Start 메서드를 호출하여 타이머를 시작합니다.
폴링 메커니즘 설정
  1. using 문을 MyNewService.cs에 추가하거나 System.Timers 네임스페이스에 대해서는 Imports 문을 MyNewService.vb에 추가합니다.

    using System.Timers;
    
    Imports System.Timers
    
  2. MyNewService.OnStart 이벤트에 다음 코드를 추가하여 폴링 메커니즘을 설정합니다.

    // Set up a timer that triggers every minute.
    Timer timer = new Timer();
    timer.Interval = 60000; // 60 seconds
    timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
    timer.Start();
    
    ' Set up a timer that triggers every minute.
    Dim timer As Timer = New Timer()
    timer.Interval = 60000 ' 60 seconds
    AddHandler timer.Elapsed, AddressOf Me.OnTimer
    timer.Start()
    
  3. MyNewService 클래스에서 멤버 변수를 추가합니다. 여기에는 이벤트 로그에 기록할 다음 이벤트의 식별자가 포함됩니다.

    private int eventId = 1;
    
    Private eventId As Integer = 1
    
  4. MyNewService 클래스에서 OnTimer 메서드를 추가하여 Timer.Elapsed 이벤트를 처리합니다.

    public void OnTimer(object sender, ElapsedEventArgs args)
    {
        // TODO: Insert monitoring activities here.
        eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId++);
    }
    
    Private Sub OnTimer(sender As Object, e As Timers.ElapsedEventArgs)
       ' TODO: Insert monitoring activities here.
       eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId)
       eventId = eventId + 1
    End Sub
    

주 스레드에서 모든 작업을 실행하는 대신 백그라운드 작업자 스레드를 사용하여 작업을 실행할 수도 있습니다. 자세한 내용은 System.ComponentModel.BackgroundWorker를 참조하세요.

서비스가 중지될 때 수행되는 동작 정의

서비스가 중지될 때 이벤트 로그에 항목을 추가하는 코드 줄을 OnStop 메서드에 삽입합니다.

protected override void OnStop()
{
    eventLog1.WriteEntry("In OnStop.");
}
Protected Overrides Sub OnStop()
    EventLog1.WriteEntry("In OnStop.")
End Sub

서비스의 다른 동작 정의

OnPause, OnContinueOnShutdown 메서드를 재정의하여 구성 요소에 대한 처리 작업을 추가로 정의할 수 있습니다.

다음 코드에서는 MyNewService 클래스에서 OnContinue 메서드를 재정의하는 방법을 보여 줍니다.

protected override void OnContinue()
{
    eventLog1.WriteEntry("In OnContinue.");
}
Protected Overrides Sub OnContinue()
    EventLog1.WriteEntry("In OnContinue.")
End Sub

서비스 상태 설정

서비스는 서비스 제어 관리자에 상태를 보고합니다. 따라서 사용자는 서비스가 정상적으로 작동 중인지를 확인할 수 있습니다. 기본적으로 ServiceBase에서 상속되는 서비스는 SERVICE_STOPPED, SERVICE_PAUSED 및 SERVICE_RUNNING을 포함하여 제한된 상태 설정 세트를 보고합니다. 서비스를 시작하는 데 시간이 걸리는 경우에는 SERVICE_START_PENDING 상태를 보고하면 도움이 됩니다.

또한 Windows SetServiceStatus 함수를 호출하는 코드를 추가하여 SERVICE_START_PENDING 및 SERVICE_STOP_PENDING 상태 설정을 구현할 수 있습니다.

서비스 보류 중 상태 구현

  1. using 문을 MyNewService.cs에 추가하거나 System.Runtime.InteropServices 네임스페이스에 대해서는 Imports 문을 MyNewService.vb에 추가합니다.

    using System.Runtime.InteropServices;
    
    Imports System.Runtime.InteropServices
    
  2. ServiceState 값을 선언하고 상태에 대한 구조(플랫폼 호출에서 사용함)를 추가하려면 MyNewService.cs 또는 MyNewService.vb에 다음 코드를 추가합니다.

    public enum ServiceState
    {
        SERVICE_STOPPED = 0x00000001,
        SERVICE_START_PENDING = 0x00000002,
        SERVICE_STOP_PENDING = 0x00000003,
        SERVICE_RUNNING = 0x00000004,
        SERVICE_CONTINUE_PENDING = 0x00000005,
        SERVICE_PAUSE_PENDING = 0x00000006,
        SERVICE_PAUSED = 0x00000007,
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct ServiceStatus
    {
        public int dwServiceType;
        public ServiceState dwCurrentState;
        public int dwControlsAccepted;
        public int dwWin32ExitCode;
        public int dwServiceSpecificExitCode;
        public int dwCheckPoint;
        public int dwWaitHint;
    };
    
    Public Enum ServiceState
        SERVICE_STOPPED = 1
        SERVICE_START_PENDING = 2
        SERVICE_STOP_PENDING = 3
        SERVICE_RUNNING = 4
        SERVICE_CONTINUE_PENDING = 5
        SERVICE_PAUSE_PENDING = 6
        SERVICE_PAUSED = 7
    End Enum
    
    <StructLayout(LayoutKind.Sequential)>
    Public Structure ServiceStatus
        Public dwServiceType As Long
        Public dwCurrentState As ServiceState
        Public dwControlsAccepted As Long
        Public dwWin32ExitCode As Long
        Public dwServiceSpecificExitCode As Long
        Public dwCheckPoint As Long
        Public dwWaitHint As Long
    End Structure
    

    참고

    서비스 제어 관리자는 SERVICE_STATUS 구조체dwWaitHintdwCheckpoint 멤버를 사용하여 Windows 서비스가 시작 또는 종료될 때까지 기다릴 시간을 결정합니다. OnStartOnStop 메서드가 오랫동안 실행되는 경우 서비스는 증분된 dwCheckPoint 값을 포함하여 SetServiceStatus을(를) 다시 호출하여 시간을 더 요청할 수 있습니다.

  3. MyNewService 클래스에서 플랫폼 호출을 사용하여 SetServiceStatus 함수를 선언합니다.

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus);
    
    Declare Auto Function SetServiceStatus Lib "advapi32.dll" (ByVal handle As IntPtr, ByRef serviceStatus As ServiceStatus) As Boolean
    
  4. SERVICE_START_PENDING 상태를 구현하려면 OnStart 메서드 시작 부분에 다음 코드를 추가합니다.

    // Update the service state to Start Pending.
    ServiceStatus serviceStatus = new ServiceStatus();
    serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
    serviceStatus.dwWaitHint = 100000;
    SetServiceStatus(this.ServiceHandle, ref serviceStatus);
    
    ' Update the service state to Start Pending.
    Dim serviceStatus As ServiceStatus = New ServiceStatus()
    serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING
    serviceStatus.dwWaitHint = 100000
    SetServiceStatus(Me.ServiceHandle, serviceStatus)
    
  5. 상태를 SERVICE_RUNNING으로 설정하려면 OnStart 메서드 끝에 코드를 추가합니다.

    // Update the service state to Running.
    serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
    SetServiceStatus(this.ServiceHandle, ref serviceStatus);
    
    ' Update the service state to Running.
    serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING
    SetServiceStatus(Me.ServiceHandle, serviceStatus)
    
  6. (선택 사항) OnStop 메서드가 장기 실행 메서드인 경우 OnStop 메서드에서 이 절차를 반복합니다. SERVICE_STOP_PENDING 상태를 구현하고 OnStop 메서드가 끝나기 전에 SERVICE_STOPPED 상태를 반환합니다.

    예를 들어:

    // Update the service state to Stop Pending.
    ServiceStatus serviceStatus = new ServiceStatus();
    serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING;
    serviceStatus.dwWaitHint = 100000;
    SetServiceStatus(this.ServiceHandle, ref serviceStatus);
    
    // Update the service state to Stopped.
    serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED;
    SetServiceStatus(this.ServiceHandle, ref serviceStatus);
    
    ' Update the service state to Stop Pending.
    Dim serviceStatus As ServiceStatus = New ServiceStatus()
    serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING
    serviceStatus.dwWaitHint = 100000
    SetServiceStatus(Me.ServiceHandle, serviceStatus)
    
    ' Update the service state to Stopped.
    serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED
    SetServiceStatus(Me.ServiceHandle, serviceStatus)
    

서비스에 설치 관리자 추가

Windows 서비스를 실행하려면 해당 서비스를 설치해야 합니다. 그러면 서비스 제어 관리자에 서비스가 등록됩니다. 등록 정보를 처리하는 설치 관리자를 프로젝트에 추가합니다.

  1. 솔루션 탐색기에서 MyNewService.cs 또는 MyNewService.vb의 바로 가기 메뉴에 있는 뷰 디자이너를 선택합니다.

  2. 디자인 뷰에서 백그라운드 영역을 선택한 다음, 바로 가기 메뉴에서 설치 관리자 추가를 선택합니다.

    기본적으로 Visual Studio는 이름이 ProjectInstaller인 구성 요소 클래스를 추가하고 여기에는 프로젝트에 대한 두 개의 설치 관리자가 포함되어 있습니다. 이러한 설치 관리자는 서비스 및 서비스에 연결된 프로세스에 사용됩니다.

  3. ProjectInstaller디자인뷰에서 Visual C# 프로젝트의 경우 serviceInstaller1을 선택하고 Visual Basic 프로젝트의 경우 ServiceInstaller1을 선택한 다음, 바로 가기 메뉴에서 속성을 선택합니다.

  4. 속성 창에서 ServiceName 속성이 MyNewService로 설정되어 있는지 확인합니다.

  5. Description 속성에 샘플 서비스와 같은 텍스트를 추가합니다.

    이 텍스트는 서비스 창의 설명 열에 표시되어 사용자에게 서비스를 설명합니다.

    서비스 창의 서비스 설명입니다.

  6. DisplayName 속성에 텍스트를 추가합니다. 예를 들어 MyNewService 표시 이름을 입력할 수 있습니다.

    이 텍스트는 서비스 창의 표시 이름 열에 표시됩니다. 이 이름은 시스템에서 사용하는 이름인 ServiceName 속성과 다를 수 있습니다(예: 시스템을 시작하는 net start 명령에 사용하는 이름).

  7. 드롭 다운 목록에서 StartType 속성을 Automatic(으)로 설정합니다.

  8. 완료되면 속성 창이 다름 그림과 같아야 합니다.

    Windows 서비스에 대한 설치 관리자 속성

  9. ProjectInstaller디자인뷰에서 Visual C# 프로젝트의 경우 serviceProcessInstaller1을 선택하고 Visual Basic 프로젝트의 경우 ServiceProcessInstaller1을 선택한 다음, 바로 가기 메뉴에서 속성을 선택합니다. 드롭 다운 목록에서 Account 속성을 LocalSystem(으)로 설정합니다.

    이 설정은 서비스를 설치하고 로컬 시스템 계정을 사용하여 실행합니다.

    중요

    LocalSystem 계정에는 광범위한 권한이 있습니다. 예를 들어, 이 계정은 이벤트 로그에 쓸 수 있습니다. 이 계정을 사용할 때는 악성 소프트웨어의 공격을 받을 가능성이 커지므로 주의해야 합니다. 다른 작업에는 LocalService 계정을 사용하는 것이 좋습니다. 이 계정은 로컬 컴퓨터에서 권한 없는 사용자의 역할을 하며 원격 서버에 익명 자격 증명을 제공합니다. LocalService 계정을 사용하는 경우 이 예제는 실패합니다. 이벤트 로그에 대한 쓰기 권한이 필요하기 때문입니다.

설치 관리자에 대한 자세한 내용은 방법: 서비스 애플리케이션에 설치 관리자 추가를 참조하세요.

(선택 사항) 시작 매개 변수 설정

참고

시작 매개 변수 추가를 결정하기 전에 시작 매개 변수가 서비스로 정보를 전달하는 가장 효율적인 방법인지를 고려합니다. 시작 매개 변수는 쉽게 사용하고 구문 분석할 수 있으며 사용자가 쉽게 재정의할 수 있지만 설명서가 없으면 사용자가 검색하고 사용하기가 어려울 수 있습니다. 일반적으로 서비스에 많은 시작 매개 변수가 필요한 경우에는 레지스트리나 구성 파일을 대신 사용해야 합니다.

Windows 서비스에는 명령줄 인수나 시작 매개 변수를 사용할 수 있습니다. 프로세스 시작 매개 변수에 코드를 추가하면 사용자가 서비스 속성 창에서 고유한 사용자 지정 시작 매개 변수로 서비스를 시작할 수 있습니다. 그러나 이러한 시작 매개 변수는 다음 번에 서비스를 시작할 때 유지되지 않습니다. 시작 매개 변수를 영구적으로 설정하려면 레지스트리에서 설정합니다.

각 Windows 서비스에는 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services 하위 키에 레지스트리 항목이 있습니다. 각 서비스의 하위 키 아래에서 매개 변수 하위 키를 사용하여 서비스가 액세스할 수 있는 정보를 저장합니다. Windows 서비스의 애플리케이션 구성 파일은 다른 프로그램 형식에서와 같은 방식으로 사용할 수 있습니다. 샘플 코드는 ConfigurationManager.AppSettings을(를) 참조하세요.

시작 매개 변수를 추가하려면

  1. Program.cs 또는 MyNewService.Designer.vb를 선택한 다음, 바로 가기 메뉴에서 코드 보기를 선택합니다. Main 메서드에서 코드를 변경해 입력 매개 변수를 추가하고 서비스 생성자에게 전달합니다.

    static void Main(string[] args)
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new MyNewService(args)
        };
        ServiceBase.Run(ServicesToRun);
    }
    
    Shared Sub Main(ByVal cmdArgs() As String)
        Dim ServicesToRun() As System.ServiceProcess.ServiceBase = New System.ServiceProcess.ServiceBase() {New MyNewService(cmdArgs)}
        System.ServiceProcess.ServiceBase.Run(ServicesToRun)
    End Sub
    
  2. MyNewService.cs 또는 MyNewService.vb에서 MyNewService 생성자를 변경하여 입력 매개 변수를 다름과 같이 처리합니다.

    using System.Diagnostics;
    
    public MyNewService(string[] args)
    {
        InitializeComponent();
    
        string eventSourceName = "MySource";
        string logName = "MyNewLog";
    
        if (args.Length > 0)
        {
           eventSourceName = args[0];
        }
    
        if (args.Length > 1)
        {
            logName = args[1];
        }
    
        eventLog1 = new EventLog();
    
        if (!EventLog.SourceExists(eventSourceName))
        {
            EventLog.CreateEventSource(eventSourceName, logName);
        }
    
        eventLog1.Source = eventSourceName;
        eventLog1.Log = logName;
    }
    
    Imports System.Diagnostics
    
    Public Sub New(ByVal cmdArgs() As String)
        InitializeComponent()
        Dim eventSourceName As String = "MySource"
        Dim logName As String = "MyNewLog"
        If (cmdArgs.Count() > 0) Then
            eventSourceName = cmdArgs(0)
        End If
        If (cmdArgs.Count() > 1) Then
            logName = cmdArgs(1)
        End If
        eventLog1 = New EventLog()
        If (Not EventLog.SourceExists(eventSourceName)) Then
            EventLog.CreateEventSource(eventSourceName, logName)
        End If
        eventLog1.Source = eventSourceName
        eventLog1.Log = logName
    End Sub
    

    이 코드는 사용자가 제공하는 시작 매개 변수에 따라 이벤트 소스와 로그 이름을 설정합니다. 인수가 제공되지 않으면 기본값이 사용됩니다.

  3. 명령줄 인수를 지정하려면 ProjectInstaller.cs 또는 ProjectInstaller.vbProjectInstaller 클래스에 다음 코드를 추가합니다.

    protected override void OnBeforeInstall(IDictionary savedState)
    {
        string parameter = "MySource1\" \"MyLogFile1";
        Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\"";
        base.OnBeforeInstall(savedState);
    }
    
    Protected Overrides Sub OnBeforeInstall(ByVal savedState As IDictionary)
        Dim parameter As String = "MySource1"" ""MyLogFile1"
        Context.Parameters("assemblypath") = """" + Context.Parameters("assemblypath") + """ """ + parameter + """"
        MyBase.OnBeforeInstall(savedState)
    End Sub
    

    일반적으로 이 값에는 Windows 서비스에 대한 실행 파일의 전체 경로가 포함됩니다. 서비스를 올바르게 시작하려면 사용자는 경로와 개별 매개 변수에 따옴표를 사용해야 합니다. 사용자는 ImagePath 레지스트리 항목에서 매개 변수를 변경하여 Windows 서비스에 대한 시작 매개 변수를 변경할 수 있습니다. 그러나 프로그래밍 방식으로 값을 변경하고 관리 또는 구성 유틸리티를 사용하는 것과 같이 사용자에게 익숙한 방식으로 기능을 노출시키는 것이 더 나은 방식입니다.

서비스 빌드

  1. 솔루션 탐색기에 있는 MyNewService 프로젝트의 바로 가기 메뉴에서 속성을 선택합니다.

    프로젝트의 속성 페이지가 나타납니다.

  2. 애플리케이션 탭의 시작 개체 목록에서 MyNewService.Program을 선택하거나 Visual Basic 프로젝트의 Sub Main을 선택합니다.

  3. 프로젝트를 빌드하려면 솔루션 탐색기를 열고 프로젝트의 바로 가기 메뉴에 있는 빌드를 선택합니다(또는 Ctrl+Shift+B를 누름).

서비스 설치

이제 Windows 서비스를 빌드했으므로 이를 설치할 수 있습니다. Windows 서비스를 설치하려면 설치할 컴퓨터에서 관리자 자격 증명이 있어야 합니다.

  1. 관리자 자격 증명을 사용하여 Visual Studio에 대한 개발자 명령 프롬프트를 엽니다.

  2. Visual Studio용 개발자 명령 프롬프트에서 프로젝트의 출력이 포함된 폴더(기본적으로 프로젝트의 \bin\Debug 하위 디렉터리)로 이동합니다.

  3. 다음 명령을 입력합니다.

    installutil MyNewService.exe
    

    서비스를 성공적으로 설치한 경우 명령이 설치에 성공했음을 보고합니다.

    시스템에서 installutil.exe를 찾을 수 없는 경우 해당 파일이 컴퓨터에 있는지 확인합니다. 이 도구는 %windir%\Microsoft.NET\Framework[64]\<프레임워크 버전> 폴더에 .NET Framework와 함께 설치됩니다. 예를 들어 64비트 버전의 기본 경로는 %windir%\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe입니다.

    installutil.exe 프로세스가 실패한 경우 설치 로그를 확인하여 이유를 찾아보세요. 기본적으로 로그는 서비스 실행 파일과 동일한 폴더에 있습니다. 다음과 같은 경우 설치에 실패할 수 있습니다.

    • RunInstallerAttribute 클래스가 ProjectInstaller 클래스에 없습니다.
    • 특성이 true(으)로 설정되지 않았습니다.
    • ProjectInstaller 클래스가 public(으)로 정의되지 않았습니다.

자세한 내용은 방법: 서비스 설치 및 제거를 참조하세요.

서비스 시작 및 실행

  1. Windows에서 서비스 데스크톱 앱을 엽니다. Windows+R을 눌러 실행 상자를 열고 services.msc를 입력한 다음, Enter 키를 누르거나 확인을 선택합니다.

    해당 서비스가 설정된 표시 이름의 사전순으로 서비스에 표시됩니다.

    서비스 창의 MyNewService입니다.

  2. 서비스를 시작하려면 서비스의 바로 가기 메뉴에서 시작을 선택합니다.

  3. 서비스를 중지하려면 서비스의 바로 가기 메뉴에서 중지를 선택합니다.

  4. (선택 사항) 명령줄에서 net start <서비스 이름>net stop <서비스 이름> 명령을 사용하여 서비스를 시작하고 중지할 수 있습니다.

서비스의 이벤트 로그 출력 확인

  1. Windows에서 이벤트 뷰어 데스크톱 앱을 엽니다. Windows 검색 창에서 이벤트 뷰어를 입력한 다음, 검색 결과에서 이벤트 뷰어를 선택합니다.

    Visual Studio의 보기 메뉴에서 서버 탐색기를 열고(또는 Ctrl+Alt+S를 누름) 로컬 컴퓨터의 이벤트 로그 노드를 확장하면 이벤트 로그에 액세스할 수 있습니다.

  2. 이벤트 뷰어에서 애플리케이션 및 서비스 로그를 확장합니다.

  3. MyNewLog(또는 절차에 따라 명령줄 인수를 추가한 경우 MyLogFile1)의 목록을 찾아서 확장합니다. 서비스에서 수행한 두 작업(시작 및 중지)의 항목이 표시됩니다.

    이벤트 뷰어를 사용하여 이벤트 로그 항목 확인

리소스 정리

Windows 서비스 앱이 더 이상 필요 없는 경우 제거할 수 있습니다.

  1. 관리자 자격 증명을 사용하여 Visual Studio에 대한 개발자 명령 프롬프트를 엽니다.

  2. Visual Studio에 대한 개발자 명령 프롬프트 창에서 프로젝트의 출력이 포함된 폴더로 이동합니다.

  3. 다음 명령을 입력합니다.

    installutil.exe /u MyNewService.exe
    

    서비스를 성공적으로 제거한 경우 명령은 서비스가 성공적으로 제거되었음을 보고합니다. 자세한 내용은 방법: 서비스 설치 및 제거를 참조하세요.

다음 단계

이제 서비스를 만들었으므로 다음을 수행할 수 있습니다.

  • 다른 사용자가 Windows 서비스를 설치하는 데 사용하는 독립 실행형 설치 프로그램을 만듭니다. WiX 도구 집합를 사용하여 Windows 서비스의 설치 관리자를 만들 수 있습니다. 다른 아이디어를 보려면 설치 관리자 패키지 만들기를 참조하세요.

  • 설치한 서비스에 명령을 보낼 수 있는 ServiceController 구성 요소를 살펴보세요.

  • 애플리케이션이 실행될 때 이벤트 로그를 만드는 것보다는 애플리케이션이 설치될 때 설치 관리자를 사용하여 이벤트 로그를 만듭니다. 애플리케이션을 제거하면 설치 관리자가 이벤트 로그를 삭제합니다. 자세한 내용은 EventLogInstaller를 참조하세요.

참조