Creative Motive
[Windows Service - 5] 시작, 중지, 일시정지 본문
데브피아 까막 님 작성 (http://crowback.tistory.com/208)
이번에는 간단하게 설치된 서비스의 시작, 중지, 일시정지, 일시정지 풀기에 관한 내용을을 짤막하게 다루어 본다.
먼저 서비스 매니저의 핸들을 얻는다. 서비스 매니저의 핸들을 이용하여, 특정 서비스를 제어하는 것이 가능하다.
SC_HANDLE hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
서비스 매니저 핸들을 이용하여, 원하는 서비스를 오픈한다.
SC_HANDLE hSrv = OpenService(hScm, "열고자 하는 서비스의 이름", SERVICE_ALL_ACCESS);
해당 서비스의 핸들을 이용하여, 서비스를 시작한다.
StartService(hSrv, 0, NULL);
해당 서비스의 핸들을 이용하여, 서비스를 중지 시킨다.
SERVICE_STATUS ss;
ControlService(hSrv, SERVICE_CONTROL_STOP, &ss);
ControlService(hSrv, SERVICE_CONTROL_STOP, &ss);
해당 서비스의 핸들을 이용하여, 서비스를 일시 중지 시킨다.
SERVICE_STATUS ss;
ControlService(hSrv, SERVICE_CONTROL_PAUSE, &ss);
ControlService(hSrv, SERVICE_CONTROL_PAUSE, &ss);
해당 서비스의 핸들을 이용하여, 일시 중지된 서비스를 재개시킨다.
SERVICE_STATUS ss;
ControlService(hSrv, SERVICE_CONTROL_CONTINUE, &ss);
ControlService(hSrv, SERVICE_CONTROL_CONTINUE, &ss);
위와 같은 형태로 서비스의 동작 상태를 변경 하였을 때, 현재의 서비스 동작 상태를 읽어온다.
SERVICE_STATUS ss;
ControlService(hSrv,SERVICE_CONTROL_INTERROGATE,&ss);
그외에 설치할 때 당시의 여러 설정이나 상태를 변경하려면
ChangeServiceConfig 혹은 ChangeServiceConfig2 를 이용하여, 다양한 변경을 가해줄 수 있다.
ControlService(hSrv,SERVICE_CONTROL_INTERROGATE,&ss);
// 지금까지 나온 SERVICE_STATUS 의 구조에 대하여 잠깐 살펴보자.
typedef struct _SERVICE_STATUS {
DWORD dwServiceType; // 서비스의 타입(파일드라이버/커널드라이버/일반서비스 ...)
DWORD dwCurrentState; // 서비스의 동작 상태
DWORD dwControlsAccepted; // 서비스가 받을 수 있는 이벤트 설정 상태
DWORD dwWin32ExitCode; // 상태 변경주 에러가 발생했을 시 에러코드
DWORD dwServiceSpecificExitCode; // 위와 같으나 좀 다르다.
DWORD dwCheckPoint; // 적당히 무시
DWORD dwWaitHint; // 적당히 무시
} SERVICE_STATUS, *LPSERVICE_STATUS;
typedef struct _SERVICE_STATUS {
DWORD dwServiceType; // 서비스의 타입(파일드라이버/커널드라이버/일반서비스 ...)
DWORD dwCurrentState; // 서비스의 동작 상태
DWORD dwControlsAccepted; // 서비스가 받을 수 있는 이벤트 설정 상태
DWORD dwWin32ExitCode; // 상태 변경주 에러가 발생했을 시 에러코드
DWORD dwServiceSpecificExitCode; // 위와 같으나 좀 다르다.
DWORD dwCheckPoint; // 적당히 무시
DWORD dwWaitHint; // 적당히 무시
} SERVICE_STATUS, *LPSERVICE_STATUS;
그외에 설치할 때 당시의 여러 설정이나 상태를 변경하려면
ChangeServiceConfig 혹은 ChangeServiceConfig2 를 이용하여, 다양한 변경을 가해줄 수 있다.
서비스의 동작을 외부에서 제어했을 경우, 내부에서는 해당 상태에 맞도록 상태 설정을 처리해 주어야 한다.
(만약 내부에서 알맞게 상태를 변경하여 주지 않으면, 외부에서는 응답없음과 같은 기괴한 동작을 할것이다.)
SERVICE_STATUS ss;
ss.dwCurrentState = 원하는 상태;
SetServiceStatus(hSrv, &ss);
/* 설정 가능한 상태
#define SERVICE_STOPPED 0x00000001
#define SERVICE_START_PENDING 0x00000002
#define SERVICE_STOP_PENDING 0x00000003
#define SERVICE_RUNNING 0x00000004
#define SERVICE_CONTINUE_PENDING 0x00000005
#define SERVICE_PAUSE_PENDING 0x00000006
#define SERVICE_PAUSED 0x00000007
*/
ss.dwCurrentState = 원하는 상태;
SetServiceStatus(hSrv, &ss);
/* 설정 가능한 상태
#define SERVICE_STOPPED 0x00000001
#define SERVICE_START_PENDING 0x00000002
#define SERVICE_STOP_PENDING 0x00000003
#define SERVICE_RUNNING 0x00000004
#define SERVICE_CONTINUE_PENDING 0x00000005
#define SERVICE_PAUSE_PENDING 0x00000006
#define SERVICE_PAUSED 0x00000007
*/
저렇게 열어준 핸들은 사용후에 받드시 닫아주어야 한다.
CloseServiceHandle(hSrv);
CloseServiceHandle(hScm);
CloseServiceHandle(hScm);
이전 장에서 서비스를 설치/제거, 여기서는 시작/중지를 확인하였으니, 다음 장에서는 서비스 본체에 대한 정리를 하고자 한다.
( 흐름을 보기 위한 부분으로 에러처리 없이 가장 간단한 형태로 설정이 되어 있으므로, 다음에는 추가적인 처리가 있을것이다.)