이번 강좌는 C#을 이용하여 윈도우의 제어판-->서비스에 등록 시키는 프로그램을 만들어 보도록 하겠습니다.
자~ 그럼 하나씩 따라 해 볼까요! (천천히 해 보자구요...)
C# 을 이용한 윈도우 서비스 프로그램 만들기 아래의 실습을 따라 하면서 윈도우에서 서비스를 등록하는 방법에 대해 이해를 하도록 하겠습니다 .
1. Visual Studio .NET 을 시작 한 후 C# 콘솔 애플리케이션을 하나 만들어 보도록 합니다 . 프로젝트 이름은 myFirstService 로 합니다 . 2. 프로젝트 안으로 들어오면 솔루션 탐색기의 Class1.cs 파일을 Application.cs 로 바꿉니다 . 이 파일은 이프로젝트의 Entry Point 이므로 직관적인 이름으로 바꾸도록 합니다 . 3. 솔루션 탐색기에서 마우스 우측 버튼을 눌러 속성창을 열어 [ 구성속성 ] --> [ 빌드 ] 에서 XML 문서 파일을 myFirstService.xml 로 바꾸도록 합니다 . 4. 닷넷 프레임워크에서는 윈도우 서비스를 구현 하기 위해 구현 해야 하는 System.ServiceProcess.ServiceBase 라는 베이스 클래스를 가집니다 . 이 클래스는 실제 서비스를 구현하고자 하는 클래스에서 상속을 받아 OnStart(), OnStop() 메소드를 재정의 (Override) 해야 합니다 . 이러한 메소드는 Service Control Manager 로부터 실제 호출 되므로 중요한 기능을 하는 함수 입니다 . OnStart 와 OnStop 메소드는 1 분에 한번씩 Service Control Manager 에게 해당 서비스가 살아 있는지 죽어 있는지에 대한 응답 (return control) 을 주어야 하므로 주의 해야 합니다 . 그러므로 이번 애플리케이션에서는 실제 서비스가 하는 일을 백그라운드 스레드를 이용하여 처리하도록 합니다 . -------------------------------------------------------
아래는 MyServiceBase.cs 파일 입니다 .
-------------------------------------------------------
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
namespace myFirstService
{
public class MyServiceBase : System.ServiceProcess.ServiceBase
{
public MyServiceBase()
{
// create a new timespan object with a default of 10 seconds delay.
m_delay = new TimeSpan(0, 0, 0, 10, 0 );
}
///
/// Set things in motion so your service can do its work.
///protected override void OnStart(string[] args)
{
// create our threadstart object to wrap our delegate method
ThreadStart ts = new ThreadStart( this.ServiceMain );
// create the manual reset event and set it to an initial state of unsignaled
m_shutdownEvent = new ManualResetEvent(false);
// create the worker thread
m_thread = new Thread( ts );
// go ahead and start the worker thread
m_thread.Start();
// call the base class so it has a chance to perform any work it needs to
base.OnStart( args );
}
///
/// Stop this service.
///protected override void OnStop()
{
// signal the event to shutdown
m_shutdownEvent.Set();
// wait for the thread to stop giving it 10 seconds
m_thread.Join(10000);
// call the base class
base.OnStop();
}
///
///
///protected void ServiceMain()
{
bool bSignaled = false;
int nReturnCode = 0;
while( true )
{
// wait for the event to be signaled or for the configured delay
bSignaled = m_shutdownEvent.WaitOne( m_delay, true );
// if we were signaled to shutdow, exit the loop
if( bSignaled == true )
break;
// let's do some work
nReturnCode = Execute();
}
}
///
///
//////
protected virtual int Execute()
{
return -1;
}
protected Thread m_thread;
protected ManualResetEvent m_shutdownEvent;
protected TimeSpan m_delay;
}
}
5. 이번에는 이전에 만든 MyServiceBase 를 상속하는 MyChildServiceBase.cs 클래스를 만들도록 합니다 . using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
namespace myFirstService
{
public class MyChildServiceBase : MyServiceBase
{
public MyChildServiceBase()
{
// TODO: Add any initialization after the InitComponent call
}
///
/// Set things in motion so your service can do its work.
///protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
base.OnStart( args );
}
///
/// Stop this service.
///protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
base.OnStop();
}
}
}
6. 이전에는 실제 AdminService 를 수행 하는 MyAdminService.cs 를 만듭니다 . using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
namespace myFirstService
{
public class MyAdminService : MyServiceBase
{
public MyAdminService()
{
this.ServiceName = "MyAdminSvc";
}
///
/// Set things in motion so your service can do its work.
///protected override void OnStart(string[] args)
{
base.OnStart( args );
}
///
/// Stop this service.
///protected override void OnStop()
{
base.OnStop();
}
///
///
//////
protected override int Execute()
{
// for right now we'll just log a message in the Application message log to let us know that
// our service is working
System.Diagnostics.EventLog.WriteEntry("MyAdminSvc", ServiceName + "::Execute()");
return 0;
}
}
}
7. 지금까지 하나의 서비스를 만들어 보았으며 이제는 Application.cs 파일의 메인 메소드를 수정 하여 실제 서비스가 기동 되도록 하겠습니다 . ( 전체 Application.cs 파일은 아래와 같습니다 ) using System;
using System.ServiceProcess;
namespace myFirstService
{
///
/// Summary description for Class1.
///class Application
{
///
/// The main entry point for the application.
///[STAThread]
static void Main (string[] args)
{
// we'll go ahead and create an array so that we can add the different services that
// we'll create over time.
ServiceBase[] servicesToRun;
// to create a new instance of a new service, just add it to the list of services
// specified in the ServiceBase array constructor.
servicesToRun = new ServiceBase[] { new MyAdminService() };
// now run all the service that we have created. This doesn't actually cause the services
// to run but it registers the services with the Service Control Manager so that it can
// when you start the service the SCM will call the OnStart method of the service.
ServiceBase.Run( servicesToRun );
}
}
}
8. 아래에서 추가될 인스톨러 (Installer) 는 제어판의 서비스에 등록 할 때 필요한 파일 입니다 . [MyInstaller.cs]
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace myFirstService
{
///
/// Summary description for SpadesInstaller.
///[RunInstaller(true)]
public class MyInstaller : System.Configuration.Install.Installer
{
public MyInstaller()
{
ServiceProcessInstaller process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
ServiceInstaller serviceAdmin = new ServiceInstaller();
serviceAdmin.StartType = ServiceStartMode.Manual;
serviceAdmin.ServiceName = "MyAdminSvc";
serviceAdmin.DisplayName = "My Administration Service";
// Microsoft didn't add the ability to add a description for the services we are going to install
// To work around this we'll have to add the information directly to the registry but I'll leave
// this exercise for later.
// now just add the installers that we created to our parents container, the documentation
// states that there is not any order that you need to worry about here but I'll still
// go ahead and add them in the order that makes sense.
Installers.Add( process );
Installers.Add( serviceAdmin );
}
}
}
9. 이젠 윈도우에 서비스를 설치 하는 일만 남았습니다 . 서비스의 설치 및 해제는 아래와 같은 방법을 이용 합니다 . installutil myFirstService.exe
installutil myFirstService.exe -U
10. 실행 파일이 있는 폴더에서 위의 명령을 실행 하여 서비스를 등록 하도록 합니다 .. 11. 제어판의 서비스에 가서 서비스가 등록 되었는지 확인 하여 봅니다 . 확인이 되면 서비스를 기동하여 보도록 합니다 . 12. 이젠 이벤트 로그를 확인하여 10 초 마다 로그가 생기는 것을 확인 하도록 합니다 .
댓글 없음:
댓글 쓰기