C#강좌, C#교육 닷넷, .NET, C#을 이용한 윈도우 서비스 프로그램 만들기, 제어판서비스프로그램, 닷넷실무교육
닷넷, .NET, C#을 이용한 윈도우 서비스 프로그램 만들기, 제어판서비스프로그램, C#강좌, C#교육, C#을 이용한 윈도우 서비스 프로그램 만들기
아래의 실습을 따라 하면서 윈도우에서 서비스를 등록하는 방법에 대해 이해를 하도록 하겠습니다.
1. Visual Studio .NET을 시작 한 후 C# 콘솔 애플리케이션을 하나 만들어 보도록 합니다. 프로젝트 이름은 myFirstService로 합니다.
2. 프로젝트 안으로 들어오면 솔루션 탐색기의 Class1.cs 파일을 Application.cs로 바꿉니다. 이 파일은 이프로젝트의 Entry Point 이므로 직관적인 이름으로 바꾸도록 합니다.…
<>
3. 솔루션 탐색기에서 마우스 우측 버튼을 눌러 속성창을 열어 [구성속성] ' [빌드] 에서 XML 문서 파일을 myFirstService.xml로 바꾸도록 합니다.
<>
<>
3. 닷넷 프레임워크에서는 윈도우 서비스를 구현 하기 위해 구현 해야 하는 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;
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 );
}
{
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 );
}
/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
// create our threadstart object to wrap our delegate method
ThreadStart ts = new ThreadStart( this.ServiceMain );
/// Set things in motion so your service can do its work.
/// </summary>
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);
m_shutdownEvent = new ManualResetEvent(false);
// create the worker thread
m_thread = new Thread( ts );
m_thread = new Thread( ts );
// go ahead and start the worker thread
m_thread.Start();
m_thread.Start();
// call the base class so it has a chance to perform any work it needs to
base.OnStart( args );
}
/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// signal the event to shutdown
m_shutdownEvent.Set();
base.OnStart( args );
}
/// <summary>
/// Stop this service.
/// </summary>
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);
m_thread.Join(10000);
// call the base class
base.OnStop();
}
base.OnStop();
}
/// <summary>
///
/// </summary>
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 );
///
/// </summary>
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;
if( bSignaled == true )
break;
// let's do some work
nReturnCode = Execute();
}
}
nReturnCode = Execute();
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
protected virtual int Execute()
{
return -1;
}
///
/// </summary>
/// <returns></returns>
protected virtual int Execute()
{
return -1;
}
protected Thread m_thread;
protected ManualResetEvent m_shutdownEvent;
protected TimeSpan m_delay;
}
}
protected ManualResetEvent m_shutdownEvent;
protected TimeSpan m_delay;
}
}
4. 이번에는 이전에 만든 MyServiceBase를 상속하는 MyChildServiceBase.cs 클래스를 만들도록 합니다.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
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
}
{
public class MyChildServiceBase : MyServiceBase
{
public MyChildServiceBase()
{
// TODO: Add any initialization after the InitComponent call
}
/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
base.OnStart( args );
}
/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
base.OnStop();
}
}
}
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
base.OnStart( args );
}
/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your service.
base.OnStop();
}
}
}
5. 이전에는 실제 AdminService를 수행 하는 MyAdminService.cs를 만듭니다.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
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";
}
{
public class MyAdminService : MyServiceBase
{
public MyAdminService()
{
this.ServiceName = "MyAdminSvc";
}
/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
base.OnStart( args );
}
/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
base.OnStop();
}
/// Set things in motion so your service can do its work.
/// </summary>
protected override void OnStart(string[] args)
{
base.OnStart( args );
}
/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
base.OnStop();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
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()");
///
/// </summary>
/// <returns></returns>
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;
}
}
}
}
}
}
6. 지금까지 하나의 서비스를 만들어 보았으며 이제는 Application.cs 파일의 메인 메소드를 수정 하여 실제 서비스가 기동 되도록 하겠습니다. . (전체 Application.cs 파일은 아래와 같습니다)
using System;
using System.ServiceProcess;
using System.ServiceProcess;
namespace myFirstService
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Application
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[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;
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Application
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[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() };
// 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 );
}
}
}
// 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 );
}
}
}
7. 아래에서 추가될 인스톨러(Installer)는 제어판의 서비스에 등록 할 때 필요한 파일 입니다.
[MyInstaller.cs]
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace myFirstService
{
/// <summary>
/// Summary description for SpadesInstaller.
/// </summary>
[RunInstaller(true)]
public class MyInstaller : System.Configuration.Install.Installer
{
public MyInstaller()
{
ServiceProcessInstaller process = new ServiceProcessInstaller();
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace myFirstService
{
/// <summary>
/// Summary description for SpadesInstaller.
/// </summary>
[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.
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 );
}
}
}
}
8. 이젠 윈도우에 서비스를 설치 하는 일만 남았다. 서비스의 설치 및 해제는 아래와 같은 방법을 이용 합니다.
installutil myFirstService.exe
installutil myFirstService.exe -U
installutil myFirstService.exe -U
9. 실행 파일이 있는 폴더에서 위의 명령을 실행 하여 서비스를 등록 하도록 합니다..
<>
10. 제어판의 서비스에 가서 서비스가 등록 되었는지 확인 하여 봅니다.
확인이 되면 서비스를 기동하여 보도록 합니다.
<>
11. 이젠 이벤트 로그를 확인하여 10초 마다 로그가 생기는 것을 확인 하도록 합니다.
<>
[개강확정강좌]오라클자바커뮤니티에서 운영하는 개발자 전문교육 ,개인80%환급(www.onjprogramming.co.kr)
[주말]
[11/2]C#,ASP.NET마스터
[11/2]Spring3.X, MyBatis, Hibernate실무과정
[11/2]JAVA&WEB프레임워크실무과정
[평일야간]
[10/29]C#,ASP.NET마스터
[10/31]JAVA&WEB프레임워크실무과정
[11/1]Spring3.X, MyBatis, Hibernate실무과정
[주간]
[11/4]Spring3.X, MyBatis, Hibernate실무과정
[주말]
[11/2]C#,ASP.NET마스터
[11/2]Spring3.X, MyBatis, Hibernate실무과정
[11/2]JAVA&WEB프레임워크실무과정
[평일야간]
[10/29]C#,ASP.NET마스터
[10/31]JAVA&WEB프레임워크실무과정
[11/1]Spring3.X, MyBatis, Hibernate실무과정
[주간]
[11/4]Spring3.X, MyBatis, Hibernate실무과정
[기타 다른 강좌는 아래 해당 카테고리를 클릭해주세요]
댓글 없음:
댓글 쓰기