Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- C
- Rxjava2
- kodility
- C/C++
- 코틀린
- NDK
- Kotlin
- Android P
- 안드로이드 구글맵
- flutter firestore
- 프로그래머스
- RxAndroid
- C++
- Django REST
- Django REST Android
- RxJava
- Android
- FLUTTER
- android architecture component
- mfc
- 안드로이드
- 알고리즘
- Flutter TextField
- dart
- livedata
- Java
- Python
- Django REST framework
- UWP
- android push
Archives
- Today
- Total
개발하는 두더지
[C/C++/MFC] 윈도우 서비스 생성/시작/중지/삭제 본문
# 빌드환경
- Windows 7/10 64bit + VS2008 sp1
# 동작 플랫폼
- Windows xp / vista / 7 / 8 / 8.1 / 10
# 윈도우 서비스란?
윈도우 서비스는 사용자에게 보이지 않지만 (UI X) , 윈도우를 부팅한 후 또는 사용자 로그인 후( Flag 설정으로 변경 가능 ) 부터 항상 실행되는 프로그램.
# 서비스 생성 조건
Main 진입점이 있는 콘솔 프로그램으로 주로 제작 ( C++ 의 경우 )
속성
일반 : 표준 Windows 라이브러리 사용
C/C++ -> 코드 생성 -> 런타임 라이브러리 : 다중 스레드(/MT) or 다중 스레드 디버그(/MTD , 용량 더 커짐)
정적 라이브러리에서 MFC 사용으로 설정했을 때와 같음 -> 재배포 패키지 없는 환경에서도 구동 가능
# 서비스 구현
- 생성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | int CService::ServiceCreate(TCHAR * serviceName, TCHAR * displayServiceName , TCHAR * exePath, TCHAR * description) { SC_HANDLE schSCManager = NULL; SC_HANDLE schService = NULL; //1. 서비스를 오픈한다. schSCManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if(schSCManager == NULL) { DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceCreate_OpenSCManager] : ")) ; return dwError; } //2. 오픈한 서비스 핸들로 서비스를 생성한다. schService = ::CreateService( schSCManager, // SCManager database serviceName, // name of service displayServiceName, // service name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // service type SERVICE_AUTO_START, // start type SERVICE_ERROR_NORMAL, // error control type exePath, // service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // no dependencies NULL, // LocalSystem account NULL); // no password if(schService == NULL) { CloseServiceHandle(schSCManager); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceCreate_CreateService] : ")) ; return dwError; } SERVICE_DESCRIPTION Desc; Desc.lpDescription = description; //3. 생성된 서비스에 서비스 설명 내용을 변경해준다. BOOL bServiceConfig = ::ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &Desc); if(bServiceConfig == FALSE) { CloseServiceHandle(schSCManager); CloseServiceHandle(schService); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceCreate_OpenSCManager] : ")) ; return dwError; } //4. 서비스 핸들모두 닫아준다. CloseServiceHandle(schSCManager); CloseServiceHandle(schService); return ERROR_NONE; } | cs |
// SERVICE_INTERACTIVE_PROCESS
로 서비스를 실행하면
서비스 -> 자신의 서비스 속성 -> 로그온 탭 -> 로컬시스템계정 ( 서비스와 테스크톱 상호 작용 허용 ) 이 체크되어있는 상태와 같음
- 실행
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | int CService::ServiceStart(TCHAR * serviceName) { SC_HANDLE schSCManager = NULL; SC_HANDLE schService = NULL; //1. 서비스를 오픈한다. schSCManager = OpenSCManager( NULL, // local computer NULL, // servicesActive database SC_MANAGER_ALL_ACCESS); // full access rights if (NULL == schSCManager) { DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceStart_OpenSCManager] : ")) ; return dwError; } //2. 서비스 이름으로 특정 서비스를 오픈한다. schService = OpenService( schSCManager, // SCM database serviceName, // name of service SERVICE_ALL_ACCESS); // full access if (schService == NULL) { CloseServiceHandle(schSCManager); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceStart_OpenService] : ")) ; return dwError; } //3. 서비스를 시작한다. BOOL bStart = ::StartService(schService, 0, NULL); if(bStart == FALSE) { CloseServiceHandle(schSCManager); CloseServiceHandle(schService); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceStart_StartService] : ")) ; return dwError; } //4. 서비스 핸들은 모두 닫아준다. CloseServiceHandle(schSCManager); CloseServiceHandle(schService); return ERROR_NONE; } | cs |
StartService 하면 밑의 내용이 포함된 exe가 실행되어야한다. (자신 프로세스도 가능)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 여기에 코드를 입력합니다. WCHAR wzBINARY[MAX_PATH] = {0}; ::GetModuleFileName(NULL, wzBINARY, MAX_PATH); if(lpCmdLine[0] == 'i') { ServiceInstall(); return 0; } else if(lpCmdLine[0] == 'u') { ServiceUninstall(); return 0; } else if(lpCmdLine[0] == 's') { ServiceStart(_TEXT("KJH")); return 0; } SERVICE_TABLE_ENTRY STE[] = { {(WCHAR*)wzNAME, (LPSERVICE_MAIN_FUNCTION)_tmain_service}, {NULL,NULL} }; // 서비스를 위해서 특별히 만들어진 구조의 함수 시작 부분을 시스템에 전달해야 한다. // 콘솔 프로그램과 다른 부분은 이렇게 등록시킨 함수가 콘솔의 main 처럼 동작한다는 점이다. // 일종의 콜백함수 포인터를 등록하면, 서비스 매니저가 이걸 호출해주는 방식이다. if(StartServiceCtrlDispatcher(STE) == FALSE) return -1; return 0; } | cs |
-중지
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | int CService::ServiceStop(TCHAR * serviceName) { SC_HANDLE schSCManager = NULL; SC_HANDLE schService = NULL; //1. 서비스를 오픈한다. schSCManager = OpenSCManager( NULL, // local computer NULL, // servicesActive database SC_MANAGER_ALL_ACCESS); // full access rights if (NULL == schSCManager) { DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceStop_OpenSCManager] : ")) ; return dwError; } //2. 서비스 이름을 이용해서 특정 서비스를 오픈한다. schService = OpenService( schSCManager, // SCM database serviceName, // name of service SERVICE_ALL_ACCESS); // full access if (schService == NULL) { CloseServiceHandle(schSCManager); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceStop_OpenService] : ")) ; return dwError; } SERVICE_STATUS ss; //3. 서비스의 상태를 요청한다. BOOL bQuery = ::QueryServiceStatus(schService, &ss); if(bQuery == FALSE) { CloseServiceHandle(schSCManager); CloseServiceHandle(schService); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceStop_QueryServiceStatus] : ")) ; return dwError; } //4. 서비스 상태가 STOP 상태가 아니라면 STOP을 요청한다. if(ss.dwCurrentState != SERVICE_STOPPED) { BOOL bControl = ::ControlService(schService, SERVICE_CONTROL_STOP, &ss); if(bControl == FALSE) { CloseServiceHandle(schSCManager); CloseServiceHandle(schService); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceStop_ControlService] : ")) ; return dwError; } ::Sleep(2000); //서비스가 2초안에 종료 되어야 한다. } //5. 서비스 핸들은 모두 닫아준다. CloseServiceHandle(schSCManager); CloseServiceHandle(schService); return ERROR_NONE; } | cs |
- 삭제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | int CService::ServiceDelete(TCHAR * serviceName) { SC_HANDLE schSCManager = NULL; SC_HANDLE schService = NULL; //1. 서비스를 오픈한다. schSCManager = OpenSCManager( NULL, // local computer NULL, // servicesActive database SC_MANAGER_ALL_ACCESS); // full access rights if (NULL == schSCManager) { DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceDelete_OpenSCManager] : ")) ; return dwError; } //2. 서비스 이름을 이용해서 특정 서비스를 오픈한다. schService = OpenService( schSCManager, // SCM database serviceName, // name of service SERVICE_ALL_ACCESS); // full access if (schService == NULL) { CloseServiceHandle(schSCManager); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceDelete_OpenService] : ")) ; return dwError; } //3. 특정 서비스를 삭제한다. BOOL bDelete = ::DeleteService(schService); if(bDelete == FALSE) { CloseServiceHandle(schSCManager); CloseServiceHandle(schService); DWORD dwError = ::GetLastError(); ErrorMsg(dwError,_TEXT("[CService::ServiceDelete_OpenService] : ")) ; return dwError; } //4. 서비스 핸들은 모두 닫아준다. CloseServiceHandle(schSCManager); CloseServiceHandle(schService); return ERROR_NONE; } | cs |
'C,C++' 카테고리의 다른 글
C++ 11/14/17 이란? (0) | 2016.07.22 |
---|---|
[C/C++/MFC] URLEncode, URLDecode (2) | 2016.07.22 |
[C/C++/MFC] C++ HTTP Web Server에서 HTTPS/SSL 사용하기 (AJAX 통신) (5) | 2016.07.22 |
[C/C++/MFC] 윈도우 서비스에서 응용 프로그램 실행하기(CreateProcessAsUser) (8) | 2016.07.22 |
[C/C++/MFC] Unicode Multibyte UTF8 변환 (0) | 2016.07.22 |
Comments