Windows 프로그래밍

Windows 서비스 프로그램 개발 - 2

2019. 1. 8. 13:29


예에~ 2탄이다!!

1탄에서 Create와 Start하는 함수를 살펴봤으니 2탄에서는 Stop과 Delete하는 함수에 대해 알아보자.


Stop 과정

BOOL CService::StopServiceProc(WCHAR *ServiceName) {
	
	CString ErrorString;

	SC_HANDLE SCMhandle = NULL;
	SC_HANDLE OpenSChandle = NULL;

	SCMhandle = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

	if (SCMhandle == NULL) {
		int Err = GetLastError();
		ErrorString.Format(L"Stop OpenSCManager : %d", Err);
		AfxMessageBox(ErrorString);
		return 0;
	}

	OpenSChandle = ::OpenService(SCMhandle, ServiceName, SERVICE_ALL_ACCESS);

	if (OpenSChandle == NULL) {
		CloseServiceHandle(SCMhandle);

		int Err = GetLastError();
		ErrorString.Format(L"Stop OpenSCManager : %d", Err);
		AfxMessageBox(ErrorString);
		return 0;
	}
	
	SERVICE_STATUS ss;

	BOOL StatusResult = ::QueryServiceStatus(OpenSChandle, &ss);

	if (StatusResult == FALSE) {
		CloseServiceHandle(SCMhandle);
		CloseServiceHandle(OpenSChandle);

		int Err = GetLastError();
		ErrorString.Format(L"Stop QueryServiceStatus : %d", Err);
		AfxMessageBox(ErrorString);
		return 0;
	}

	if (ss.dwCurrentState != SERVICE_STOPPED) {
		BOOL ControlResult = ::ControlService(OpenSChandle, SERVICE_CONTROL_STOP, &ss);

		if (!ControlResult) {
			CloseServiceHandle(SCMhandle);
			CloseServiceHandle(OpenSChandle);

			int Err = GetLastError();
			ErrorString.Format(L"Stop ControlService : %d", Err);
			AfxMessageBox(ErrorString);
			return 0;
		}
	}

	CloseServiceHandle(SCMhandle);
	CloseServiceHandle(OpenSChandle);

	return TRUE;
}

Create든 Start든 Stop이든 다 같아 보여서 사기치는줄 알 수도 있지만 실제로 다 비슷하다.


이번에도 역시 서비스를 제어하기 위해 SCManager를 열어준다. 물론 옵션도 SC_MANAGER_ALL_ACCESS로.

SCManager가 정상적으로 열렸다면 OpenService를 통해 서비스의 핸들을 받고 QueryServiceStatus 함수에서 해당 서비스의 상태를 알아낸다. (이렇게 함수를 표시하니까 더 찾기 쉬운 것 같다. 앞으론 이렇게 해야지)


서비스가 SERVICE_STOPPED 말 그대로 정지한 상태가 아니라면 ControlService 함수를 통해 정지시켜준다.


Delete 과정

BOOL CService::DeleteServiceProc(WCHAR *ServiceName) {
	
	CString ErrorString;

	SC_HANDLE SCMhandle = NULL;
	SC_HANDLE OpenSChandle = NULL;

	SCMhandle = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

	if (SCMhandle == NULL) {
		int Err = GetLastError();
		ErrorString.Format(L"Stop OpenSCManager : %d", Err);
		AfxMessageBox(ErrorString);
		return 0;
	}

	OpenSChandle = ::OpenService(SCMhandle, ServiceName, SERVICE_ALL_ACCESS);

	if (OpenSChandle == NULL) {
		CloseServiceHandle(SCMhandle);

		int Err = GetLastError();
		ErrorString.Format(L"Stop OpenSCManager : %d", Err);
		AfxMessageBox(ErrorString);
		return 0;
	}

	BOOL DeleteResult = ::DeleteService(OpenSChandle);

	if (DeleteResult == FALSE) {
		CloseServiceHandle(SCMhandle);
		CloseServiceHandle(OpenSChandle);

		int Err = GetLastError();
		ErrorString.Format(L"Stop OpenSCManager : %d", Err);
		AfxMessageBox(ErrorString);
		return 0;
	}

	CloseServiceHandle(SCMhandle);
	CloseServiceHandle(OpenSChandle);

	return TRUE;
}

이제 SCManager와 서비스를 여는 단계까지는 익숙할 것이다.


Delete 과정은 Stop 과정보다 더 쉽다. 그냥 DeleteService 함수를 통해 지워주면 끝이다.

이렇게 서비스를 제어하는 모든 과정은 다 알았다. 다음 글에서는 서비스에서 다른 프로그램을 실행하는 방법을 알아보자.