본문 바로가기
IT-개발,DB

[개발] .NET 프레임워크 클래스 라이브러리 - ServiceBase 클래스

by SB리치퍼슨 2010. 8. 17.

서비스 응용 프로그램의 일부로 존재할 서비스에 기본 클래스를 제공합니다. ServiceBase는 새 서비스 클래스를 만들 때 파생되어야 합니다.

네임스페이스: System.ServiceProcess
어셈블리: System.ServiceProcess(system.serviceprocess.dll)
언어 : C# / C++ 
// C# language example
C#
public class ServiceBase : Component
// C++ language example
C++
public ref class ServiceBase : public Component


설명


서비스 응용 프로그램에 있는 서비스 클래스를 정의할 때 ServiceBase에서 파생됩니다. 임의의 유용한 서비스가 OnStartOnStop 메서드를 재정의합니다. 추가 기능의 경우, 서비스 상태의 변경 내용에 대한 특정 동작을 사용하여 OnPauseOnContinue를 재정의할 수 있습니다.

서비스는 사용자 인터페이스를 지원하지 않는 장기 실행 파일이며, 사용자 계정으로 로그온한 상태에서는 실행되지 않습니다. 이 서비스는 컴퓨터에 로그온 중인 사용자 없이도 실행될 수 있습니다.

기본적으로 서비스는 System 계정으로 실행됩니다. System 계정은 Administrator 계정과는 다르며, System 계정의 권한은 변경할 수 없습니다. 또한 ServiceProcessInstaller를 사용하여 서비스를 실행할 사용자 계정을 지정할 수 있습니다.

실행 파일은 두 가지 이상의 서비스를 포함할 수 있지만 각 서비스에 대해 별도의 ServiceInstaller를 포함해야 합니다. ServiceInstaller 인스턴스는 서비스를 시스템에 등록합니다. 설치 관리자는 또한 각 서비스를 서비스 명령을 기록하는 데 사용할 수 있는 이벤트 로그와 연결합니다. 실행 파일에 있는 main() 함수는 실행할 서비스를 정의합니다. 서비스의 현재 작업 디렉터리는 실행 파일이 있는 디렉터리가 아니라 시스템 디렉터리입니다.

서비스가 시작되면 시스템에서는 실행 파일을 찾아 해당 파일 내에 포함된 서비스에 대한 OnStart 메서드를 실행시킵니다. 그러나 서비스를 실행하는 것과 실행 파일을 실행하는 것은 다릅니다. 실행 파일은 서비스를 로드만 하지만, 서비스는 서비스 제어 관리자를 통해 시작 및 중지하는 방법으로 액세스됩니다.

사용자가 서비스에서 시작 명령을 처음으로 호출하면 실행 파일에서 ServiceBase 파생 클래스의 생성자를 호출합니다. OnStart 명령 처리 메서드는 생성자가 실행된 직후에 호출됩니다. 생성자는 서비스가 처음 로드된 이후에 다시 실행되지 않으므로 생성자에서 수행한 프로세스와 OnStart에서 수행한 프로세스를 구분해야 합니다. OnStop을 사용하여 해제할 수 있는 리소스는 OnStart를 사용하여 만들어야 합니다. OnStop에서 리소스를 해제한 다음 서비스를 다시 시작하면 생성자에서 리소스를 만들 때 리소스가 제대로 만들어지지 않습니다.

SCM(서비스 제어 관리자)은 서비스와 상호 작용하는 방법을 제공합니다. SCM을 사용하여 시작, 중지, 일시 중지, 계속 또는 사용자 지정 명령을 서비스에 전달할 수 있습니다. SCM은 CanStopCanPauseAndContinue의 값을 사용하여 서비스에서 중지, 일시 중지 또는 계속 명령을 허용할지 여부를 결정합니다. 서비스 클래스에 있는 해당 속성인 CanStop 또는 CanPauseAndContinuetrue인 경우에만 SCM의 상황에 맞는 메뉴에서 중지, 일시 중지 및 계속을 사용할 수 있습니다. 명령을 사용할 수 있는 경우, 명령은 서비스에 전달되고 OnStop, OnPause 또는 OnContinue가 호출됩니다. CanStop, CanShutdown 또는 CanPauseAndContinuefalse이면 OnStop과 같은 해당 명령 처리 메서드가 구현되어 있어도 처리되지 않습니다.

SCM이 사용자 인터페이스를 사용하여 수행하는 작업을 ServiceController 클래스를 사용하여 프로그래밍 방식으로 수행할 수 있습니다. 콘솔에서 사용할 수 있는 작업을 자동화할 수 있습니다. CanStop, CanShutdown 또는 CanPauseAndContinuetrue이지만 해당 명령 처리 메서드(예: OnStop)를 구현하지 않은 경우 시스템에서 예외가 throw되고 해당 명령이 무시됩니다.

ServiceBase에 있는 OnStart, OnStop 또는 다른 메서드는 구현하지 않아도 됩니다. 그러나 서비스의 동작이 OnStart에 설명되어 있으므로 이 멤버를 재정의해야 합니다. 실행 파일의 main() 함수에 서비스의 이름을 설정해야 합니다. main()에 설정한 서비스 이름은 서비스 설치 관리자의 ServiceName 속성과 정확하게 일치해야 합니다.

InstallUtil.exe를 사용하여 시스템에 서비스를 설치할 수 있습니다.


예제


다음 예제에서는 ServiceBase 클래스에서 간단한 서비스 구현을 파생합니다. 이 서비스는 중지, 시작, 일시 중지, 계속 및 사용자 지정 명령을 포함한 다양한 서비스 명령을 처리합니다.

C#

// Turn on logging to the event log.
#define LOGEVENTS
using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ServiceSample
{
    // Define custom commands for the SimpleService.
    public enum SimpleServiceCustomCommands { StopWorker = 128, RestartWorker, CheckWorker };
    [StructLayout(LayoutKind.Sequential)]
    public struct SERVICE_STATUS
    {
        public int serviceType;
        public int currentState;
        public int controlsAccepted;
        public int win32ExitCode;
        public int serviceSpecificExitCode;
        public int checkPoint;
        public int waitHint;
    }
    public enum State
    {
        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,
    }
    // Define a simple service implementation.
    public class SimpleService : System.ServiceProcess.ServiceBase
    {
        private static int userCount = 0;
        private static ManualResetEvent pause = new ManualResetEvent(false);
        [DllImport("ADVAPI32.DLL", EntryPoint = "SetServiceStatus")]
        public static extern bool SetServiceStatus(
                        IntPtr hServiceStatus,
                        SERVICE_STATUS lpServiceStatus
                        );
        private SERVICE_STATUS myServiceStatus;
        private Thread workerThread = null;
        public SimpleService()
        {
            CanPauseAndContinue = true;
            CanHandleSessionChangeEvent = true;
            ServiceName = "SimpleService";
        }
        static void Main()
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() +
                " - Service main method starting...");
#endif
            // Load the service into memory.
            System.ServiceProcess.ServiceBase.Run(new SimpleService());
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() +
                " - Service main method exiting...");
#endif
        }
        private void InitializeComponent()
        {
            // Initialize the operating properties for the service.
            this.CanPauseAndContinue = true;
            this.CanShutdown = true;
            this.CanHandleSessionChangeEvent = true;
            this.ServiceName = "SimpleService";
        }
        // Start the service.
        protected override void OnStart(string[] args)
        {
            IntPtr handle = this.ServiceHandle;
            myServiceStatus.currentState = (int)State.SERVICE_START_PENDING;
            SetServiceStatus(handle, myServiceStatus);
            // Start a separate thread that does the actual work.
            if ((workerThread == null) ||
                ((workerThread.ThreadState &
                 (System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() +
                    " - Starting the service worker thread.");
#endif
                workerThread = new Thread(new ThreadStart(ServiceWorkerMethod));
                workerThread.Start();
            }
            if (workerThread != null)
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() +
                    " - Worker thread state = " +
                    workerThread.ThreadState.ToString());
#endif
            }
            myServiceStatus.currentState = (int)State.SERVICE_RUNNING;
            SetServiceStatus(handle, myServiceStatus);
        }
        // Stop this service.
        protected override void OnStop()
        {
            // New in .NET Framework version 2.0.
            this.RequestAdditionalTime(4000);
            // Signal the worker thread to exit.
            if ((workerThread != null) && (workerThread.IsAlive))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() +
                    " - Stopping the service worker thread.");
#endif
                pause.Reset();
                Thread.Sleep(5000);
                workerThread.Abort();
            }
            if (workerThread != null)
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() +
                    " - OnStop Worker thread state = " +
                    workerThread.ThreadState.ToString());
#endif
            }
            // Indicate a successful exit.
            this.ExitCode = 0;
        }
        // Pause the service.
        protected override void OnPause()
        {
            // Pause the worker thread.
            if ((workerThread != null) &&
                (workerThread.IsAlive) &&
                ((workerThread.ThreadState &
                 (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) == 0))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() +
                    " - Pausing the service worker thread.");
#endif
                pause.Reset();
                Thread.Sleep(5000);
            }
            if (workerThread != null)
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() +
                    " OnPause - Worker thread state = " +
                    workerThread.ThreadState.ToString());
#endif
            }
        }
        // Continue a paused service.
        protected override void OnContinue()
        {
            // Signal the worker thread to continue.
            if ((workerThread != null) &&
                ((workerThread.ThreadState &
                 (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) != 0))
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() +
                    " - Resuming the service worker thread.");
#endif
                pause.Set();
            }
            if (workerThread != null)
            {
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() +
                    " OnContinue - Worker thread state = " +
                    workerThread.ThreadState.ToString());
#endif
            }
        }
        // Handle a custom command.
        protected override void OnCustomCommand(int command)
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() +
                " - Custom command received: " +
                command.ToString());
#endif
            // If the custom command is recognized,
            // signal the worker thread appropriately.
            switch (command)
            {
                case (int)SimpleServiceCustomCommands.StopWorker:
                    // Signal the worker thread to terminate.
                    // For this custom command, the main service
                    // continues to run without a worker thread.
                    OnStop();
                    break;
                case (int)SimpleServiceCustomCommands.RestartWorker:
                    // Restart the worker thread if necessary.
                    OnStart(null);
                    break;
                case (int)SimpleServiceCustomCommands.CheckWorker:
#if LOGEVENTS
                    // Log the current worker thread state.
                    EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() +
                        " OnCustomCommand - Worker thread state = " +
                        workerThread.ThreadState.ToString());
#endif
                    break;
                default:
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnCustomCommand",
                        DateTime.Now.ToLongTimeString());
#endif
                    break;
            }
        }
        // Handle a session change notice
        protected override void OnSessionChange(SessionChangeDescription changeDescription)
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() +
                " - Session change notice received: " +
                changeDescription.Reason.ToString() + "  Session ID: " +
                changeDescription.SessionId.ToString());
#endif
            switch (changeDescription.Reason)
            {
                case SessionChangeReason.SessionLogon:
                    userCount += 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionLogon, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.SessionLogoff:
                    userCount -= 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionLogoff, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.RemoteConnect:
                    userCount += 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " RemoteConnect, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.RemoteDisconnect:
                    userCount -= 1;
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " RemoteDisconnect, total users: " +
                        userCount.ToString());
#endif
                    break;
                case SessionChangeReason.SessionLock:
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionLock");
#endif
                    break;
                case SessionChangeReason.SessionUnlock:
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.OnSessionChange",
                        DateTime.Now.ToLongTimeString() +
                        " SessionUnlock");
#endif
                    break;
                default:
                    break;
            }
        }
        // Define a simple method that runs as the worker thread for
        // the service. 
        public void ServiceWorkerMethod()
        {
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                " - Starting the service worker thread.");
#endif
            try
            {
                do
                {
                    // Simulate 4 seconds of work.
                    Thread.Sleep(4000);
                    // Block if the service is paused or is shutting down.
                    pause.WaitOne();
#if LOGEVENTS
                    EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                        " - heartbeat cycle.");
#endif
                }
                while (true);
            }
            catch (ThreadAbortException)
            {
                // Another thread has signalled that this worker
                // thread must terminate.  Typically, this occurs when
                // the main service thread receives a service stop
                // command.
                // Write a trace line indicating that the worker thread
                // is exiting.  Notice that this simple thread does
                // not have any local objects or data to clean up.
#if LOGEVENTS
                EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                    " - Thread abort signaled.");
#endif
            }
#if LOGEVENTS
            EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +
                " - Exiting the service worker thread.");
#endif
        }
    }
}


// C++ language example
// Turn on the constant for trace output.
#define TRACE

#using <System.ServiceProcess.dll>
#using <System.dll>

using namespace System;
using namespace System::ComponentModel;
using namespace System::IO;
using namespace System::ServiceProcess;
using namespace System::Threading;
using namespace System::Diagnostics;

// Define custom commands for the SimpleService.
public enum class SimpleServiceCustomCommands
{
    StopWorker = 128,
    RestartWorker, CheckWorker
};


// Define a simple service implementation.
public ref class SimpleService: public System::ServiceProcess::ServiceBase
{
private:
    Thread^ workerThread;
    int userCount;
public:
    SimpleService()
    {
        CanPauseAndContinue = true;
        ServiceName = "SimpleService";
        workerThread = nullptr;
        CanHandleSessionChangeEvent = true;
    }

private:

    void InitializeComponent()
    {
        // Initialize the operating properties for the service.
        this->CanPauseAndContinue = true;
        this->CanShutdown = true;
        this->ServiceName = "SimpleService";
        this->CanHandleSessionChangeEvent = true;
    }

    // Start the service.
protected:
    virtual void OnStart( array<String^>^  ) override
    {
        // Start a separate thread that does the actual work.
        if ( (workerThread == nullptr) || ((workerThread->ThreadState & (System::Threading::ThreadState::Unstarted | System::Threading::ThreadState::Stopped)) != (System::Threading::ThreadState)0) )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Starting the service worker thread.", "OnStart" );
            workerThread = gcnew Thread( gcnew ThreadStart( this,&SimpleService::ServiceWorkerMethod ) );
            workerThread->Start();
        }

        if ( workerThread != nullptr )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Worker thread state = " + workerThread->ThreadState.ToString(), "OnStart" );
        }
    }

    // Stop this service.
protected:
    virtual void OnStop() override
    {
        // Signal the worker thread to exit.
        if ( (workerThread != nullptr) && (workerThread->IsAlive) )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Stopping the service worker thread.", "OnStop" );
            workerThread->Abort();

            // Wait up to 500 milliseconds for the thread to terminate.
            workerThread->Join( 500 );
        }

        if ( workerThread != nullptr )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Worker thread state = " + workerThread->ThreadState.ToString(), "OnStop" );
        }
    }

    // Pause the service.
protected:
    virtual void OnPause() override
    {
        // Pause the worker thread.
        if ( (workerThread != nullptr) && (workerThread->IsAlive) && ((workerThread->ThreadState & (System::Threading::ThreadState::Suspended | System::Threading::ThreadState::SuspendRequested)) == (System::Threading::ThreadState)0) )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Suspending the service worker thread.", "OnPause" );
            workerThread->Suspend();
        }

        if ( workerThread != nullptr )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Worker thread state = " + workerThread->ThreadState.ToString(), "OnPause" );
        }
    }

    // Continue a paused service.
protected:
    virtual void OnContinue() override
    {
        // Signal the worker thread to continue.
        if ( (workerThread != nullptr) && ((workerThread->ThreadState & (System::Threading::ThreadState::Suspended | System::Threading::ThreadState::SuspendRequested)) != (System::Threading::ThreadState)0) )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Resuming the service worker thread.", "OnContinue" );
            workerThread->Resume();
        }

        if ( workerThread != nullptr )
        {
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Worker thread state = " + workerThread->ThreadState.ToString(), "OnContinue" );
        }
    }

    // Handle a custom command.
protected:
    virtual void OnCustomCommand( int command ) override
    {
        Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Custom command received: " + command, "OnCustomCommand" );

        // If the custom command is recognized,
        // signal the worker thread appropriately.
        switch ( command )
        {
        case (int)SimpleServiceCustomCommands::StopWorker:

            // Signal the worker thread to terminate.
            // For this custom command, the main service
            // continues to run without a worker thread.
            OnStop();
            break;

        case (int)SimpleServiceCustomCommands::RestartWorker:

            // Restart the worker thread if necessary.
            OnStart( nullptr );
            break;

        case (int)SimpleServiceCustomCommands::CheckWorker:

            // Log the current worker thread state.
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Worker thread state = " + workerThread->ThreadState.ToString(), "OnCustomCommand" );
            break;

        default:
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Unrecognized custom command ignored!", "OnCustomCommand" );
            break;
        }
    }
protected:
    virtual void OnSessionChange(SessionChangeDescription changeDescription) override
    {
        Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Change description received: "
            + changeDescription.ToString(), "OnSessionChange" );

        switch (changeDescription.Reason)
        {
        case SessionChangeReason::SessionLogon:
            userCount += 1;
            Trace::WriteLine( DateTime::Now.ToLongTimeString() +
                " SessionLogon, total users: " +
                userCount.ToString(), "OnSessionChange" );
            break;
        case SessionChangeReason::SessionLogoff:
            userCount -= 1;
            Trace::WriteLine( DateTime::Now.ToLongTimeString() +
                " SessionLogoff, total users: " +
                userCount.ToString(), "OnSessionChange" );
            break;
        case SessionChangeReason::RemoteConnect:
            userCount += 1;
            Trace::WriteLine( DateTime::Now.ToLongTimeString() +
                " RemoteConnect, total users: " +
                userCount.ToString(), "OnSessionChange" );
            break;
        case SessionChangeReason::RemoteDisconnect:
            userCount -= 1;
            Trace::WriteLine( DateTime::Now.ToLongTimeString() +
                " RemoteDisconnect, total users: " +
                userCount.ToString(), "OnSessionChange" );
            break;
        case SessionChangeReason::SessionLock:
            Trace::WriteLine( DateTime::Now.ToLongTimeString() +
                " SessionLock", "OnSessionChange" );
            break;
        case SessionChangeReason::SessionUnlock:
Trace::WriteLine( DateTime::Now.ToLongTimeString() +
                " SessionUnlock", "OnSessionChange" );
            break;

        default:
            Trace::WriteLine( DateTime::Now.ToLongTimeString() +
                " - Unhandled session change event.", "OnSessionChange" );
            break;
        }
    }
    // Define a simple method that runs as the worker thread for
    // the service. 
public:
    void ServiceWorkerMethod()
    {
        Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Starting the service worker thread.", "Worker" );
        try
        {
            for ( ; ;  )
            {

                // Wake up every 10 seconds and write
                // a message to the trace output.
                Thread::Sleep( 10000 );
                Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - heartbeat cycle.", "Worker" );
            }
        }
        catch ( ThreadAbortException^ )
        {
            // Another thread has signalled that this worker
            // thread must terminate.  Typically, this occurs when
            // the main service thread receives a service stop
            // command.
            // Write a trace line indicating that the worker thread
            // is exiting.  Notice that this simple thread does
            // not have any local objects or data to clean up.
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Thread abort signaled.", "Worker" );
        }

        Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Exiting the service worker thread.", "Worker" );
    }
};

int main()
{
    String^ logFile = "C:\\service_log.txt";
    TextWriterTraceListener^ serviceTraceListener = nullptr;

    // Create a log file for trace output.
    // A new file is created each time.  If a
    // previous log file exists, it is overwritten.
    StreamWriter^ myFile = File::CreateText( logFile );

    // Create a new trace listener that writes to the text file,
    // and add it to the collection of trace listeners.
    serviceTraceListener = gcnew TextWriterTraceListener( myFile );
    Trace::Listeners->Add( serviceTraceListener );
    Trace::AutoFlush = true;
    Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Service main method starting...", "Main" );

    // Load the service into memory.
    System::ServiceProcess::ServiceBase::Run( gcnew SimpleService );
    Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Service main method exiting...", "Main" );

    // Remove and close the trace listener for this service.
    Trace::Listeners->Remove( serviceTraceListener );
    serviceTraceListener->Close();
    serviceTraceListener = nullptr;
    myFile->Close();
}

상속 계층 구조

System.Object
   System.MarshalByRefObject
     System.ComponentModel.Component
      System.ServiceProcess.ServiceBase
스레드로부터의 안전성

이 형식의 모든 public static(Visual Basic의 경우 Shared) 멤버는 스레드로부터 안전합니다. 인터페이스 멤버는 스레드로부터 안전하지 않습니다.

플랫폼

Windows 98, Windows 2000 SP4, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition

.NET Framework에서 모든 플래폼의 모든 버전을 지원하지는 않습니다. 지원되는 버전의 목록은 시스템 요구 사항을 참조하십시오.

버전 정보

.NET Framework

2.0, 1.1, 1.0에서 지원

참고항목

Servicebase 멤버
System.ServiceProcess 네임스페이스
ServiceProcessInstaller
ServiceInstaller



출처 : http://msdn.microsoft.com/ko-kr/library/system.serviceprocess.servicebase(v=VS.80).aspx
반응형

댓글