자습서: Windows 서비스 앱 만들기Tutorial: Create a Windows service app

이 문서에서는 이벤트 로그에 메시지를 쓰는 Windows 서비스 앱을 Visual Studio에서 만드는 방법을 보여 줍니다.This article demonstrates how to create a Windows service app in Visual Studio that writes messages to an event log.

서비스 만들기Create a service

우선 프로젝트를 만들고 서비스가 제대로 작동하는 데 필요한 값을 설정합니다.To begin, create the project and set the values that are required for the service to function correctly.

  1. Visual Studio 파일 메뉴에서 새로 만들기 > 프로젝트를 선택하거나 Ctrl+Shift+N을 눌러 새 프로젝트 창을 엽니다.From the Visual Studio File menu, select New > Project (or press Ctrl+Shift+N) to open the New Project window.

  2. Windows 서비스(.NET Framework) 프로젝트 템플릿을 검색하여 선택합니다.Navigate to and select the Windows Service (.NET Framework) project template. 템플릿을 찾으려면 설치됨Visual C# 또는 Visual Basic을 차례로 확장한 후 Windows 데스크톱을 선택합니다.To find it, expand Installed and Visual C# or Visual Basic, then select Windows Desktop. 또는 오른쪽 상단의 검색 상자에서 Windows 서비스를 입력하고 Enter 키를 누릅니다.Or, enter Windows Service in the search box on the upper right and press Enter.

    Visual Studio의 새 프로젝트 대화 상자에 있는 Windows 서비스 템플릿

    참고

    Windows 서비스 템플릿이 표시되지 않는 경우 .NET 데스크톱 개발 워크로드를 설치해야 할 수 있습니다.If you don't see the Windows Service template, you may need to install the .NET desktop development workload:

    새 프로젝트 대화 상자의 왼쪽 하단에서 Visual Studio 설치 관리자 열기를 선택합니다.In the New Project dialog, select Open Visual Studio Installer on the lower left. .NET 데스크톱 개발 워크로드를 선택한 다음, 수정을 선택합니다.Select the .NET desktop development workload, and then select Modify.

  3. 이름에서 MyNewService를 입력한 다음, 확인을 선택합니다.For Name, enter MyNewService, and then select OK.

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

    프로젝트 템플릿은 System.ServiceProcess.ServiceBase에서 상속된 Service1이라는 구성 요소 클래스를 포함합니다.The project template includes a component class named Service1 that inherits from System.ServiceProcess.ServiceBase. 여기에는 서비스를 시작하는 코드 등의 많은 기본 서비스 코드가 포함됩니다.It includes much of the basic service code, such as the code to start the service.

서비스 이름 바꾸기Rename the service

서비스 이름을 Service1에서 MyNewService로 바꿉니다.Rename the service from Service1 to MyNewService.

  1. 솔루션 탐색기에서 Service1.cs 또는 Service1.vb를 선택하고 바로 가기 메뉴에서 이름 바꾸기를 선택합니다.In Solution Explorer, select Service1.cs, or Service1.vb, and choose Rename from the shortcut menu. 파일 이름을 MyNewService.cs 또는 MyNewService.vb로 바꾼 다음, Enter 키를 누릅니다.Rename the file to MyNewService.cs, or MyNewService.vb, and then press Enter

    코드 요소 Service1에 대한 모든 참조 이름을 변경할지 여부를 묻는 팝업 창이 나타납니다.A pop-up window appears asking whether you would like to rename all references to the code element Service1.

  2. 팝업 창에서 를 선택합니다.In the pop-up window, select Yes.

    이름 바꾸기 프롬프트Rename prompt

  3. 디자인 탭의 바로 가기 메뉴에서 속성을 선택합니다.In the Design tab, select Properties from the shortcut menu. 속성 창에서 ServiceName 값을 MyNewService로 변경합니다.From the Properties window, change the ServiceName value to MyNewService.

    서비스 속성Service properties

  4. 파일 메뉴에서 모두 저장을 선택합니다.Select Save All from the File menu.

서비스에 기능 추가Add features to the service

다음 섹션에서는 Windows 서비스에 사용자 지정 이벤트 로그를 추가합니다.In this section, you add a custom event log to the Windows service. Windows 서비스에 추가할 수 있는 구성 요소 종류의 한 예로 EventLog 구성 요소를 사용합니다.The EventLog component is an example of the type of component you can add to a Windows service.

사용자 지정 이벤트 로그 기능 추가Add custom event log functionality

  1. 솔루션 탐색기에서 MyNewService.cs 또는 MyNewService.vb의 바로 가기 메뉴에 있는 뷰 디자이너를 선택합니다.In Solution Explorer, from the shortcut menu for MyNewService.cs, or MyNewService.vb, choose View Designer.

  2. 도구 상자에서 구성 요소를 확장한 다음, EventLog 구성 요소를 Service1.cs [디자인] 또는 Service1.vb [디자인] 탭으로 끕니다.In Toolbox, expand Components, and then drag the EventLog component to the Service1.cs [Design], or Service1.vb [Design] tab.

  3. 솔루션 탐색기에서 MyNewService.cs 또는 MyNewService.vb의 바로 가기 메뉴에 있는 코드 보기를 선택합니다.In Solution Explorer, from the shortcut menu for MyNewService.cs, or MyNewService.vb, choose View Code.

  4. 사용자 지정 이벤트 로그를 정의합니다.Define a custom event log. C#에서는 기존 MyNewService() 생성자를 편집하고 Visual Basic에서는 New() 생성자를 추가합니다.For C#, edit the existing MyNewService() constructor; for Visual Basic, add the New() constructor:

    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에 추가합니다.Add a using statement to MyNewService.cs (if it doesn't already exist), or an Imports statement MyNewService.vb, for the System.Diagnostics namespace:

    using System.Diagnostics;
    
    Imports System.Diagnostics
    
  6. 파일 메뉴에서 모두 저장을 선택합니다.Select Save All from the File menu.

서비스가 시작될 때 수행되는 동작 정의Define what occurs when the service starts

MyNewService.cs 또는 MyNewService.vb의 코드 편집기에서 OnStart 메서드를 찾습니다. Visual Studio는 프로젝트를 만들 때 자동으로 빈 메서드 정의를 만듭니다.In the code editor for MyNewService.cs or MyNewService.vb, locate the OnStart method; Visual Studio automatically created an empty method definition when you created the project. 서비스가 시작될 때 이벤트 로그에 항목을 기록하는 코드를 추가합니다.Add code that writes an entry to the event log when the service starts:

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

폴링Polling

서비스 애플리케이션은 오랫동안 실행되도록 설계되므로 대개 OnStart 메서드에서 설정한 시스템을 폴링하거나 모니터링합니다.Because a service application is designed to be long-running, it usually polls or monitors the system, which you set up in the OnStart method. 서비스의 작업이 시작되고 나면 OnStart 메서드가 운영 체제에 반환되어야 시스템이 차단되지 않습니다.The OnStart method must return to the operating system after the service's operation has begun so that the system isn't blocked.

간단한 폴링 메커니즘을 설정하려면 System.Timers.Timer 구성 요소를 사용합니다.To set up a simple polling mechanism, use the System.Timers.Timer component. 타이머가 일정 간격으로 Elapsed 이벤트를 발생시키며 서비스는 이벤트가 발생했을 때 모니터링을 수행할 수 있습니다.The timer raises an Elapsed event at regular intervals, at which time your service can do its monitoring. Timer 구성 요소는 다음과 같이 사용합니다.You use the Timer component as follows:

  • MyNewService.OnStart 메서드에서 Timer 구성 요소의 속성을 설정합니다.Set the properties of the Timer component in the MyNewService.OnStart method.
  • Start 메서드를 호출하여 타이머를 시작합니다.Start the timer by calling the Start method.
폴링 메커니즘을 설정합니다.Set up the polling mechanism.
  1. MyNewService.OnStart 이벤트에 다음 코드를 추가하여 폴링 메커니즘을 설정합니다.Add the following code in the MyNewService.OnStart event to set up the polling mechanism:

    // 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()
    
  2. using 문을 MyNewService.cs에 추가하거나 System.Timers 네임스페이스에 대해서는 Imports 문을 MyNewService.vb에 추가합니다.Add a using statement to MyNewService.cs, or an Imports statement to MyNewService.vb, for the System.Timers namespace:

    using System.Timers;
    
    Imports System.Timers
    
  3. MyNewService 클래스에서 OnTimer 메서드를 추가하여 Timer.Elapsed 이벤트를 처리합니다.In the MyNewService class, add the OnTimer method to handle the Timer.Elapsed event:

    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
    
  4. MyNewService 클래스에서 멤버 변수를 추가합니다.In the MyNewService class, add a member variable. 여기에는 이벤트 로그에 기록할 다음 이벤트의 식별자가 포함됩니다.It contains the identifier of the next event to write into the event log:

    private int eventId = 1;
    
    Private eventId As Integer = 1
    

주 스레드에서 모든 작업을 실행하는 대신 백그라운드 작업자 스레드를 사용하여 작업을 실행할 수도 있습니다.Instead of running all your work on the main thread, you can run tasks by using background worker threads. 자세한 내용은 System.ComponentModel.BackgroundWorker를 참조하세요.For more information, see System.ComponentModel.BackgroundWorker.

서비스가 중지될 때 수행되는 동작 정의Define what occurs when the service is stopped

서비스가 중지될 때 이벤트 로그에 항목을 추가하는 코드 줄을 OnStop 메서드에 삽입합니다.Insert a line of code in the OnStop method that adds an entry to the event log when the service is stopped:

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

서비스의 다른 동작 정의Define other actions for the service

OnPause, OnContinueOnShutdown 메서드를 재정의하여 구성 요소에 대한 처리 작업을 추가로 정의할 수 있습니다.You can override the OnPause, OnContinue, and OnShutdown methods to define additional processing for your component.

다음 코드에서는 MyNewService 클래스에서 OnContinue 메서드를 재정의하는 방법을 보여 줍니다.The following code shows how you to override the OnContinue method in the MyNewService class:

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

서비스 상태 설정Set service status

서비스는 서비스 제어 관리자에 상태를 보고합니다. 따라서 사용자는 서비스가 정상적으로 작동 중인지를 확인할 수 있습니다.Services report their status to the Service Control Manager so that a user can tell whether a service is functioning correctly. 기본적으로 ServiceBase에서 상속되는 서비스는 SERVICE_STOPPED, SERVICE_PAUSED 및 SERVICE_RUNNING을 포함하여 제한된 상태 설정 세트를 보고합니다.By default, a service that inherits from ServiceBase reports a limited set of status settings, which include SERVICE_STOPPED, SERVICE_PAUSED, and SERVICE_RUNNING. 서비스를 시작하는 데 시간이 걸리는 경우에는 SERVICE_START_PENDING 상태를 보고하면 도움이 됩니다.If a service takes a while to start up, it's useful to report a SERVICE_START_PENDING status.

또한 Windows SetServiceStatus 함수를 호출하는 코드를 추가하여 SERVICE_START_PENDING 및 SERVICE_STOP_PENDING 상태 설정을 구현할 수 있습니다.You can implement the SERVICE_START_PENDING and SERVICE_STOP_PENDING status settings by adding code that calls the Windows SetServiceStatus function.

서비스 보류 중 상태 구현Implement service pending status

  1. using 문을 MyNewService.cs에 추가하거나 System.Runtime.InteropServices 네임스페이스에 대해서는 Imports 문을 MyNewService.vb에 추가합니다.Add a using statement to MyNewService.cs, or an Imports statement to MyNewService.vb, for the System.Runtime.InteropServices namespace:

    using System.Runtime.InteropServices;
    
    Imports System.Runtime.InteropServices
    
  2. ServiceState 값을 선언하고 상태에 대한 구조(플랫폼 호출에서 사용함)를 추가하려면 MyNewService.cs 또는 MyNewService.vb에 다음 코드를 추가합니다.Add the following code to MyNewService.cs, or MyNewService.vb, to declare the ServiceState values and to add a structure for the status, which you'll use in a platform invoke call:

    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 서비스가 시작 또는 종료될 때까지 기다릴 시간을 결정합니다.The Service Control Manager uses the dwWaitHint and dwCheckpoint members of the SERVICE_STATUS structure to determine how much time to wait for a Windows service to start or shut down. OnStartOnStop 메서드가 오랫동안 실행되는 경우 서비스는 증분된 dwCheckPoint 값을 포함하여 SetServiceStatus을(를) 다시 호출하여 시간을 더 요청할 수 있습니다.If your OnStart and OnStop methods run long, your service can request more time by calling SetServiceStatus again with an incremented dwCheckPoint value.

  3. MyNewService 클래스에서 플랫폼 호출을 사용하여 SetServiceStatus 함수를 선언합니다.In the MyNewService class, declare the SetServiceStatus function by using platform invoke:

    [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 메서드 시작 부분에 다음 코드를 추가합니다.To implement the SERVICE_START_PENDING status, add the following code to the beginning of the OnStart method:

    // 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 메서드 끝에 코드를 추가합니다.Add code to the end of the OnStart method to set the status to SERVICE_RUNNING:

    // 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 메서드에서 이 절차를 반복합니다.(Optional) If OnStop is a long-running method, repeat this procedure in the OnStop method. SERVICE_STOP_PENDING 상태를 구현하고 OnStop 메서드가 끝나기 전에 SERVICE_STOPPED 상태를 반환합니다.Implement the SERVICE_STOP_PENDING status and return the SERVICE_STOPPED status before the OnStop method exits.

    예를 들어:For example:

    // 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)
    

서비스에 설치 관리자 추가Add installers to the service

Windows 서비스를 실행하려면 해당 서비스를 설치해야 합니다. 그러면 서비스 제어 관리자에 서비스가 등록됩니다.Before you run a Windows service, you need to install it, which registers it with the Service Control Manager. 등록 정보를 처리하는 설치 관리자를 프로젝트에 추가합니다.Add installers to your project to handle the registration details.

  1. 솔루션 탐색기에서 MyNewService.cs 또는 MyNewService.vb의 바로 가기 메뉴에 있는 뷰 디자이너를 선택합니다.In Solution Explorer, from the shortcut menu for MyNewService.cs, or MyNewService.vb, choose View Designer.

  2. 디자인 뷰에서 백그라운드 영역을 선택한 다음, 바로 가기 메뉴에서 설치 관리자 추가를 선택합니다.In the Design view, select the background area, then choose Add Installer from the shortcut menu.

    기본적으로 Visual Studio는 이름이 ProjectInstaller인 구성 요소 클래스를 추가하고 여기에는 프로젝트에 대한 두 개의 설치 관리자가 포함되어 있습니다.By default, Visual Studio adds a component class named ProjectInstaller, which contains two installers, to your project. 이러한 설치 관리자는 서비스 및 서비스에 연결된 프로세스에 사용됩니다.These installers are for your service and for the service's associated process.

  3. ProjectInstaller디자인뷰에서 Visual C# 프로젝트의 경우 serviceInstaller1을 선택하고 Visual Basic 프로젝트의 경우 ServiceInstaller1을 선택한 다음, 바로 가기 메뉴에서 속성을 선택합니다.In the Design view for ProjectInstaller, select serviceInstaller1 for a Visual C# project, or ServiceInstaller1 for a Visual Basic project, then choose Properties from the shortcut menu.

  4. 속성 창에서 ServiceName 속성이 MyNewService로 설정되어 있는지 확인합니다.In the Properties window, verify the ServiceName property is set to MyNewService.

  5. Description 속성에 샘플 서비스와 같은 텍스트를 추가합니다.Add text to the Description property, such as A sample service.

    이 텍스트는 서비스 창의 설명 열에 표시되어 사용자에게 서비스를 설명합니다.This text appears in the Description column of the Services window and describes the service to the user.

    서비스 창의 서비스 설명입니다.Service description in the Services window.

  6. DisplayName 속성에 텍스트를 추가합니다.Add text to the DisplayName property. 예를 들어 MyNewService 표시 이름을 입력할 수 있습니다.For example, MyNewService Display Name.

    이 텍스트는 서비스 창의 표시 이름 열에 표시됩니다.This text appears in the Display Name column of the Services window. 이 이름은 시스템에서 사용하는 이름인 ServiceName 속성과 다를 수 있습니다(예: 시스템을 시작하는 net start 명령에 사용하는 이름).This name can be different from the ServiceName property, which is the name the system uses (for example, the name you use for the net start command to start your service).

  7. 드롭 다운 목록에서 StartType 속성을 Automatic(으)로 설정합니다.Set the StartType property to Automatic from the drop-down list.

  8. 완료되면 속성 창이 다름 그림과 같아야 합니다.When you're finished, the Properties windows should look like the following figure:

    Windows 서비스에 대한 설치 관리자 속성Installer Properties for a Windows service

  9. ProjectInstaller디자인뷰에서 Visual C# 프로젝트의 경우 serviceProcessInstaller1을 선택하고 Visual Basic 프로젝트의 경우 ServiceProcessInstaller1을 선택한 다음, 바로 가기 메뉴에서 속성을 선택합니다.In the Design view for ProjectInstaller, choose serviceProcessInstaller1 for a Visual C# project, or ServiceProcessInstaller1 for a Visual Basic project, then choose Properties from the shortcut menu. 드롭 다운 목록에서 Account 속성을 LocalSystem(으)로 설정합니다.Set the Account property to LocalSystem from the drop-down list.

    이 설정은 서비스를 설치하고 로컬 시스템 계정을 사용하여 실행합니다.This setting installs the service and runs it by using the local system account.

    중요

    LocalSystem 계정에는 광범위한 권한이 있습니다. 예를 들어, 이 계정은 이벤트 로그에 쓸 수 있습니다.The LocalSystem account has broad permissions, including the ability to write to the event log. 이 계정을 사용할 때는 악성 소프트웨어의 공격을 받을 가능성이 커지므로 주의해야 합니다.Use this account with caution, because it might increase your risk of attacks from malicious software. 다른 작업에는 LocalService 계정을 사용하는 것이 좋습니다. 이 계정은 로컬 컴퓨터에서 권한 없는 사용자의 역할을 하며 원격 서버에 익명 자격 증명을 제공합니다.For other tasks, consider using the LocalService account, which acts as a non-privileged user on the local computer and presents anonymous credentials to any remote server. LocalService 계정을 사용하는 경우 이 예제는 실패합니다. 이벤트 로그에 대한 쓰기 권한이 필요하기 때문입니다.This example fails if you try to use the LocalService account, because it needs permission to write to the event log.

설치 관리자에 대한 자세한 내용은 방법: 서비스 애플리케이션에 설치 관리자 추가를 참조하세요.For more information about installers, see How to: Add installers to your service application.

(선택 사항) 시작 매개 변수 설정(Optional) Set startup parameters

참고

시작 매개 변수 추가를 결정하기 전에 시작 매개 변수가 서비스로 정보를 전달하는 가장 효율적인 방법인지를 고려합니다.Before you decide to add startup parameters, consider whether it's the best way to pass information to your service. 시작 매개 변수는 쉽게 사용하고 구문 분석할 수 있으며 사용자가 쉽게 재정의할 수 있지만 설명서가 없으면 사용자가 검색하고 사용하기가 어려울 수 있습니다.Although they're easy to use and parse, and a user can easily override them, they might be harder for a user to discover and use without documentation. 일반적으로 서비스에 많은 시작 매개 변수가 필요한 경우에는 레지스트리나 구성 파일을 대신 사용해야 합니다.Generally, if your service requires more than just a few startup parameters, you should use the registry or a configuration file instead.

Windows 서비스에는 명령줄 인수나 시작 매개 변수를 사용할 수 있습니다.A Windows service can accept command-line arguments, or startup parameters. 프로세스 시작 매개 변수에 코드를 추가하면 사용자가 서비스 속성 창에서 고유한 사용자 지정 시작 매개 변수로 서비스를 시작할 수 있습니다.When you add code to process startup parameters, a user can start your service with their own custom startup parameters in the service properties window. 그러나 이러한 시작 매개 변수는 다음 번에 서비스를 시작할 때 유지되지 않습니다.However, these startup parameters aren't persisted the next time the service starts. 시작 매개 변수를 영구적으로 설정하려면 레지스트리에서 설정합니다.To set startup parameters permanently, set them in the registry.

각 Windows 서비스에는 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services 하위 키에 레지스트리 항목이 있습니다.Each Windows service has a registry entry under the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services subkey. 각 서비스의 하위 키 아래에서 매개 변수 하위 키를 사용하여 서비스가 액세스할 수 있는 정보를 저장합니다.Under each service's subkey, use the Parameters subkey to store information that your service can access. Windows 서비스의 애플리케이션 구성 파일은 다른 프로그램 형식에서와 같은 방식으로 사용할 수 있습니다.You can use application configuration files for a Windows service the same way you do for other types of programs. 샘플 코드는 ConfigurationManager.AppSettings을(를) 참조하세요.For sample code, see ConfigurationManager.AppSettings.

시작 매개 변수를 추가하려면To add startup parameters

  1. Program.cs 또는 MyNewService.Designer.vb를 선택한 다음, 바로 가기 메뉴에서 코드 보기를 선택합니다.Select Program.cs, or MyNewService.Designer.vb, then choose View Code from the shortcut menu. Main 메서드에서 코드를 변경해 입력 매개 변수를 추가하고 서비스 생성자에게 전달합니다.In the Main method, change the code to add an input parameter and pass it to the service constructor:

    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 생성자를 변경하여 입력 매개 변수를 다름과 같이 처리합니다.In MyNewService.cs, or MyNewService.vb, change the MyNewService constructor to process the input parameter as follows:

    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
    

    이 코드는 사용자가 제공하는 시작 매개 변수에 따라 이벤트 소스와 로그 이름을 설정합니다.This code sets the event source and log name according to the startup parameters that the user supplies. 인수가 제공되지 않으면 기본값이 사용됩니다.If no arguments are supplied, it uses default values.

  3. 명령줄 인수를 지정하려면 ProjectInstaller.cs 또는 ProjectInstaller.vbProjectInstaller 클래스에 다음 코드를 추가합니다.To specify the command-line arguments, add the following code to the ProjectInstaller class in ProjectInstaller.cs, or ProjectInstaller.vb:

    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 서비스에 대한 실행 파일의 전체 경로가 포함됩니다.Typically, this value contains the full path to the executable for the Windows service. 서비스를 올바르게 시작하려면 사용자는 경로와 개별 매개 변수에 따옴표를 사용해야 합니다.For the service to start up correctly, the user must supply quotation marks for the path and each individual parameter. 사용자는 ImagePath 레지스트리 항목에서 매개 변수를 변경하여 Windows 서비스에 대한 시작 매개 변수를 변경할 수 있습니다.A user can change the parameters in the ImagePath registry entry to change the startup parameters for the Windows service. 그러나 프로그래밍 방식으로 값을 변경하고 관리 또는 구성 유틸리티를 사용하는 것과 같이 사용자에게 익숙한 방식으로 기능을 노출시키는 것이 더 나은 방식입니다.However, a better way is to change the value programmatically and expose the functionality in a user-friendly way, such as by using a management or configuration utility.

서비스 빌드Build the service

  1. 솔루션 탐색기에 있는 MyNewService 프로젝트의 바로 가기 메뉴에서 속성을 선택합니다.In Solution Explorer, choose Properties from the shortcut menu for the MyNewService project.

    프로젝트의 속성 페이지가 나타납니다.The property pages for your project appear.

  2. 애플리케이션 탭의 시작 개체 목록에서 MyNewService.Program을 선택하거나 Visual Basic 프로젝트의 Sub Main을 선택합니다.On the Application tab, in the Startup object list, choose MyNewService.Program, or Sub Main for Visual Basic projects.

  3. 프로젝트를 빌드하려면 솔루션 탐색기를 열고 프로젝트의 바로 가기 메뉴에 있는 빌드를 선택합니다(또는 Ctrl+Shift+B를 누름).To build the project, in Solution Explorer, choose Build from the shortcut menu for your project (or press Ctrl+Shift+B).

서비스 설치Install the service

이제 Windows 서비스를 빌드했으므로 이를 설치할 수 있습니다.Now that you've built the Windows service, you can install it. Windows 서비스를 설치하려면 설치할 컴퓨터에서 관리자 자격 증명이 있어야 합니다.To install a Windows service, you must have administrator credentials on the computer where it's installed.

  1. 관리자 자격 증명을 사용하여 Visual Studio에 대한 개발자 명령 프롬프트를 엽니다.Open Developer Command Prompt for Visual Studio with administrative credentials. Windows 시작 메뉴에서 Visual Studio 폴더에 있는 VS 2017에 대한 개발자 명령 프롬프트를 선택한 다음, 바로 가기 메뉴에서 자세히 > 관리자로 실행을 선택합니다.From the Windows Start menu, select Developer Command Prompt for VS 2017 in the Visual Studio folder, then select More > Run as Administrator from the shortcut menu.

  2. Visual Studio에 대한 개발자 명령 프롬프트 창에서 프로젝트의 출력이 포함된 폴더(기본적으로 프로젝트의 \bin\Debug 하위 디렉터리)로 이동합니다.In the Developer Command Prompt for Visual Studio window, navigate to the folder that contains your project's output (by default, the \bin\Debug subdirectory of your project).

  3. 다음 명령을 입력합니다.Enter the following command:

    installutil MyNewService.exe
    

    서비스를 성공적으로 설치한 경우 명령이 설치에 성공했음을 보고합니다.If the service installs successfully, the command reports success.

    시스템에서 installutil.exe를 찾을 수 없는 경우 해당 파일이 컴퓨터에 있는지 확인합니다.If the system can't find installutil.exe, make sure that it exists on your computer. 이 도구는 %windir%\Microsoft.NET\Framework[64]\<프레임워크 버전> 폴더에 .NET Framework와 함께 설치됩니다.This tool is installed with the .NET Framework to the folder %windir%\Microsoft.NET\Framework[64]\<framework version>. 예를 들어 64비트 버전의 기본 경로는 %windir%\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe입니다.For example, the default path for the 64-bit version is %windir%\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe.

    installutil.exe 프로세스가 실패한 경우 설치 로그를 확인하여 이유를 찾아보세요.If the installutil.exe process fails, check the install log to find out why. 기본적으로 로그는 서비스 실행 파일과 동일한 폴더에 있습니다.By default, the log is in the same folder as the service executable. 다음과 같은 경우 설치에 실패할 수 있습니다.The installation can fail if:

    • RunInstallerAttribute 클래스가 ProjectInstaller 클래스에 없습니다.The RunInstallerAttribute class isn't present on the ProjectInstaller class.
    • 특성이 true(으)로 설정되지 않았습니다.The attribute isn't set to true.
    • ProjectInstaller 클래스가 public(으)로 정의되지 않았습니다.The ProjectInstaller class isn't defined as public.

자세한 내용은 방법: 서비스 설치 및 제거를 참조하세요.For more information, see How to: Install and uninstall services.

서비스 시작 및 실행Start and run the service

  1. Windows에서 서비스 데스크톱 앱을 엽니다.In Windows, open the Services desktop app. Windows+R을 눌러 실행 상자를 열고 services.msc를 입력한 다음, Enter 키를 누르거나 확인을 선택합니다.Press Windows+R to open the Run box, enter services.msc, and then press Enter or select OK.

    해당 서비스가 설정된 표시 이름의 사전순으로 서비스에 표시됩니다.You should see your service listed in Services, displayed alphabetically by the display name that you set for it.

    서비스 창의 MyNewService입니다.

  2. 서비스를 시작하려면 서비스의 바로 가기 메뉴에서 시작을 선택합니다.To start the service, choose Start from the service's shortcut menu.

  3. 서비스를 중지하려면 서비스의 바로 가기 메뉴에서 중지를 선택합니다.To stop the service, choose Stop from the service's shortcut menu.

  4. (선택 사항) 명령줄에서 net start <서비스 이름>net stop <서비스 이름> 명령을 사용하여 서비스를 시작하고 중지할 수 있습니다.(Optional) From the command line, use the commands net start <service name> and net stop <service name> to start and stop your service.

서비스의 이벤트 로그 출력 확인Verify the event log output of your service

  1. Windows에서 이벤트 뷰어 데스크톱 앱을 엽니다.In Windows, open the Event Viewer desktop app. Windows 검색 창에서 이벤트 뷰어를 입력한 다음, 검색 결과에서 이벤트 뷰어를 선택합니다.Enter Event Viewer in the Windows search bar, and then select Event Viewer from the search results.

    Visual Studio의 보기 메뉴에서 서버 탐색기를 열고(또는 Ctrl+Alt+S를 누름) 로컬 컴퓨터의 이벤트 로그 노드를 확장하면 이벤트 로그에 액세스할 수 있습니다.In Visual Studio, you can access event logs by opening Server Explorer from the View menu (or press Ctrl+Alt+S) and expanding the Event Logs node for the local computer.

  2. 이벤트 뷰어에서 애플리케이션 및 서비스 로그를 확장합니다.In Event Viewer, expand Applications and Services Logs.

  3. MyNewLog(또는 절차에 따라 명령줄 인수를 추가한 경우 MyLogFile1)의 목록을 찾아서 확장합니다.Locate the listing for MyNewLog (or MyLogFile1 if you followed the procedure to add command-line arguments) and expand it. 서비스에서 수행한 두 작업(시작 및 중지)의 항목이 표시됩니다.You should see the entries for the two actions (start and stop) that your service performed.

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

리소스 정리Clean up resources

Windows 서비스 앱이 더 이상 필요 없는 경우 제거할 수 있습니다.If you no longer need the Windows service app, you can remove it.

  1. 관리자 자격 증명을 사용하여 Visual Studio에 대한 개발자 명령 프롬프트를 엽니다.Open Developer Command Prompt for Visual Studio with administrative credentials.

  2. Visual Studio에 대한 개발자 명령 프롬프트 창에서 프로젝트의 출력이 포함된 폴더로 이동합니다.In the Developer Command Prompt for Visual Studio window, navigate to the folder that contains your project's output.

  3. 다음 명령을 입력합니다.Enter the following command:

    installutil.exe /u MyNewService.exe
    

    서비스를 성공적으로 제거한 경우 명령은 서비스가 성공적으로 제거되었음을 보고합니다.If the service uninstalls successfully, the command reports that your service was successfully removed. 자세한 내용은 방법: 서비스 설치 및 제거를 참조하세요.For more information, see How to: Install and uninstall services.

다음 단계Next steps

이제 서비스를 만들었으므로 다음을 수행할 수 있습니다.Now that you've created the service, you can:

  • 다른 사용자가 Windows 서비스를 설치하는 데 사용하는 독립 실행형 설치 프로그램을 만듭니다.Create a standalone setup program for others to use to install your Windows service. WiX 도구 집합를 사용하여 Windows 서비스의 설치 관리자를 만들 수 있습니다.Use the WiX Toolset to create an installer for a Windows service. 다른 아이디어를 보려면 설치 관리자 패키지 만들기를 참조하세요.For other ideas, see Create an installer package.

  • 설치한 서비스에 명령을 보낼 수 있는 ServiceController 구성 요소를 살펴보세요.Explore the ServiceController component, which enables you to send commands to the service you've installed.

  • 애플리케이션이 실행될 때 이벤트 로그를 만드는 것보다는 애플리케이션이 설치될 때 설치 관리자를 사용하여 이벤트 로그를 만듭니다.Instead of creating the event log when the application runs, use an installer to create an event log when you install the application. 애플리케이션을 제거하면 설치 관리자가 이벤트 로그를 삭제합니다.The event log is deleted by the installer when you uninstall the application. 자세한 내용은 EventLogInstaller를 참조하세요.For more information, see EventLogInstaller.

참조See also