윈도우즈 서비스 라이브러리
RTFM/기타 2010. 9. 17. 01:00Ron Wilson 의 윈도우즈 서비스 라이브러리
경우에 따라서는 응용 프로그램이 일반적인 형태의 데스크탑 응용 프로그램이 아닌 윈도우즈 서비스 형태로 구현되어야 하는 경우가 있습니다.
물론 비주얼 스튜디오를 이용하면 상당히 편리하게 서비스를 개발할 수 있긴 하지만, 그래도 디버깅과 서비스 설치 등에 있어 일반적인 응용 프로그램 보다는 번거로운 것이 사실입니다.
최근에 어줍잖은 윈도우즈 서비스를 하나 만드는 과정에서 Ron Wilson 이라는 분의 윈도우즈 서비스 라이브러리를 알게 됐는데, 그 유용함에 매료되어 이를 널리 알리고자 합니다.
Ron Wilson 이 코드 프로젝트에 쓴 원문은 아래와 같습니다.
http://www.codeproject.com/KB/system/SimpleServiceDotNet.aspx
간단히 요약하자면 이 라이브러리를 이용하면,
1. Windows Service 가 아닌 Console 프로젝트를 사용하기 때문에, 일반적인 콘솔 프로그램의 편리함을 그대로 유지할 수 있습니다.
2. 빌드한 결과물인 exe 파일을 바로 서비스로 등록할 수 있어, 번거로운 서비스 설치 작업(InstallUtil.exe)이 필요하지 않습니다.
라고 할 수 있겠습니다.
서비스 작성 연습
이 글에서는 이 라이브러리를 사용하여 간단한 윈도우즈 서비스를 구축하는 과정을 보여드릴까 합니다.
하루에 한 번 하드디스크의 용량을 체크하여 관리자에게 메일을 보내는 서비스를 개발하도록 하겠습니다.
프로젝트의 생성과 구성
먼저 콘솔 프로젝트를 하나 만듭니다.
이름은 WindowsServiceDemo 라고 하지요.
Ron 의 기사에서 라이브러리를 다운 받고, 그 중 아래 세 파일을 WindowsServiceDemo 프로젝트에 추가합니다.
ISimpleServiceWorker.cs |
WindowsServiceDemo 프로젝트에 아래 어셈블리에 대한 참조를 추가합니다.
System.configuration.dll System.Configuration.Install.dll System.Management.dll System.ServiceProcess.dll |
프로젝트의 등록 정보의 설정 탭에서 새로운 설정 파일을 추가합니다.
설정 파일을 열어 아래 값을 입력해 둡니다.
MailReceivers 는 메일을 받을 수신자 목록입니다. ; 으로 각 메일 주소를 구분합니다.
HoursToWork 는 하루 중 서비스가 동작할 시각의 목록입니다. 각 시각은 역시 ; 으로 구분합니다.
예를 들어 2;14 라는 것은 이 서비스가 2시와 14시에 한 번씩 실행된다는 의미입니다.
Utility 클래스
Utililty 클래스를 하나 추가한 후 몇 가지 헬퍼 메서드를 추가합니다.
이 글에서는 윈도우즈 서비스에 집중하기 위해 이 헬퍼 메서드에 대한 설명을 생략하지만, 좀 더 자세한 것은 주석과 첨부파일에 있는 소스를 참고하십시오.
먼저 시스템에 부착되어 있는 모든 논리 디스크의 이름과 남은 용량을 반환하는 메서드입니다.
그리고 지메일을 통해 이메일을 발송하는 메서드를 추가합니다.
마지막으로 string.Split 메서드의 래퍼 메서드를 하나 추가합니다.
Worker 클래스
이제 본격적인 서비스 작업을 구현할 차례인데요.
먼저 이 작업을 할 Worker 클래스를 추가합니다.
Worker 클래스는 Ron 의 라이브러리에 있는 ISimpleServiceWorker 인터페이스에 있는 세 가지 메서드를 구현하여야 하는데,
이 중 Init 와 Cleanrup 메서드는 각각 리소스의 할당과 해제를 담당합니다.
우리의 서비스에선 별도의 리소스를 사용하지 않으므로 그냥 비워둡니다.
실질적인 서비스의 코드는 Run 메서드 안의 무한 루프에 있습니다.
먼저 현재 시각을 체크하여 서비스가 동작할 시각인지를 체크합니다.
서비스가 동작할 시간이 맞다면, 하드디스크의 남은 용량을 검사한 후 이메일을 발송합니다.
이 루프를 매 1시간 마다 반복합니다.
타이머
서비스 프로그램, 특히 우리의 예제와 같은 로그성의 서비스를 만들 때 가장 어려운 문제 중 하나는 아마도 타이머를 만드는 일일 것입니다.
이 예제에서는 간단하게 현재의 시각(hour)이 예약된 시각(hour)과 같은지를 검사하는 로직을 사용하겠습니다.
IsTimeToWork() 메서드는 서비스가 일할 시간인지를 알려주는 역할을 합니다.
예를 들어, 설정 파일에서 Settings.Default.HoursToWork 에 2:14 라고 입력을 하였다면,
현재 시간이 2시 몇 분 이거나 14시 몇 분 이면 이 메서드는 true 를 반환합니다.
하드디스크의 남은 용량 조사
CheckFreeSpace 메서드는 하드디스크의 남은 용량을 조사하여 StringBuilder 에 기록해 두는 일을 합니다.
메일 발송
설정 파일에 저장된 수신 목록의 각 이메일 주소에 대해 메일을 발송합니다.
모든 메일이 성공적으로 발송되면 true 를 반환합니다.
1. 물론 “지메일 아이디”와 “지메일 비밀번호”에는 맞는 값을 입력하여 합니다. 2. 지메일에서 하루에 보낼 수 있는 메일의 양에는 제한이 있습니다. 대충 100통 정도인 걸로 기억이 되는데, 확실하지는 않습니다. |
디버깅
이제 서비스가 제대로 동작하는 지 테스트를 해 봅시다.
Program.cs 의 아래와 같이 변경합니다.
Ron 의 라이브러리를 사용하기 때문에 이 서비스를 실행하기 위해서는 실행파일의 끝에 –console 이라는 매개변수를 붙이면 됩니다.
Debug 모드에서는 매번 매개변수를 붙이기 힘드니까 비주얼 스튜디오에서 이 매개변수를 지정하겠습니다.
프로젝트의 등록 정보에서 아래와 같이 설정합니다.
F5 를 눌러 디버깅을 시작하면 서비스가 동작하는 것을 확인할 수 있습니다.
설정 파일의 HoursToWork 값을 현재 시간으로 맞춰놓고 테스트를 해보시기 바랍니다.
배포와 설치
마지막 단계는 개발한 서비스를 배포하고 설치하는 것입니다.
배포를 하기 위해서는 일단 Relese 모드로 빌드를 하고, bin\Release 폴더에 생성된 파일을 모두 배포할 컴퓨터에 복사를 합니다.
먼저 배포할 컴퓨터에서 명령창을 열어 아래와 같이 입력하여 도움말을 확인해보겠습니다.
현재는 서비스를 설치를 해야 하기 때문에 –install 옵션을 사용해야겠습니다.
그럼 아래와 같이 입력을 해야겠네요.
설치가 되었습니다.
설치된 서비스를 시작할 때는 –start 옵션을 사용합니다.
물론 서비스를 삭제할 때는 –uninstall 을 지정하면 됩니다.
정리
Ron Wilson 의 윈도우즈 서비스 라이브러리를 사용하면 윈도우즈 서비스를 아주 편리하게 개발/디버깅/설치할 수 있습니다.
감히 윈도우즈 서비스 개발의 (one of the) best practice 라고도 할 수 있을 것 같습니다.