//제가 다 짠건 아니구 이것 저것 편집해서 만든겁니다.
//제가 넘 화려한 C++이나 넘 딱딱한 코드는 않좋아해서 좀 바꿔 봤습니다.
//MFC사용 할려구 몇개 추가 했습니다.
// 다 보실 필요는 없구요 ServiceMainFn만 보시면 됩니다
//아래 소스를 콘솔로 컴파일 하시고 cmd에서 install하면 컴퓨터 관리 서비스에 등록 되며
//remove하시면 서비스에서 사라 집니다 (물론 서비스 진행 중이라면 내려 가지 안습니다)
//자동으로 실행하실지 수동으로 실행 하실지 옵션과 장애가 있을시 자동시작 하실지 여부는
//컴퓨터 관리 서비스에서 해주시기 바랍니다
if ( _stricmp( "install", argv[1]+1 ) == 0 )
{
InstallService();
}
else if ( _stricmp( "remove", argv[1]+1 ) == 0 )
#include "stdafx.h"
#include "winsvc.h"
DWORD g_dwNowState = 0; //현재 상태
SERVICE_STATUS_HANDLE g_hSrv = 0; //서비스 모듈의 핸들
HANDLE g_hExitEvent = 0; //나가기 위핸 핸들
static SERVICE_STATUS g_sStatus;
void ServiceMainFn(DWORD argc, LPTSTR *argv);
void ServiceHandlerFn(DWORD opCode);
void WriteDebug(LPCTSTR szDebug)
{
FILE * fp = fopen("c:\\디버그 파일.txt" , "at");
fprintf(fp , szDebug);
fclose(fp);
}
BOOL InstallService()
{
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
TCHAR szError[MAX_PATH] = {0, };
BOOL bRet = FALSE;
TCHAR szPath[512] = {0, };
if ( ::GetModuleFileName( NULL, szPath, 512 ) == 0 )
{
WriteDebug("Unable to install RealRoadInfo \n");
printf("Unable to install RealRoadInfo \n");
return bRet;
}
schSCManager = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS );
if ( NULL != schSCManager )
{
schService = ::CreateService(
schSCManager, // SCManager database
"RealRoadInfo", // name of service
"RealRoadInfo", // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier (종속성을 추가해 주는 부분 )
NULL, // dependencies
NULL, // LocalSystem account
NULL); // no password
if ( NULL != schService )
{
SERVICE_DESCRIPTION srvdesc = {0, };
srvdesc.lpDescription = "설명 입니다.";
if(FALSE == ::ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &srvdesc))
{
WriteDebug("ChangeServiceConfig2 Error \n");
printf("ChangeServiceConfig2 Error \n");
bRet = FALSE;
}
printf("RealRoadInfo installed \n");
WriteDebug("RealRoadInfo installed \n");
::CloseServiceHandle(schService);
bRet = TRUE;
}
else
{
printf("CreateService failed \n");
WriteDebug("CreateService failed \n");
bRet = FALSE;
}
::CloseServiceHandle(schSCManager);
}
else
{
printf("OpenSCManager failed \n");
WriteDebug("OpenSCManager failed \n");
bRet = FALSE;
}
if(FALSE == bRet)
{
return FALSE;
}
return bRet;
}
BOOL RemoveService()
{
SC_HANDLE schService = NULL;
SC_HANDLE schSCManager = NULL;
TCHAR szError[MAX_PATH] = {0, };
BOOL bRet = FALSE;
schSCManager = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS );
if ( NULL != schSCManager )
{
schService = ::OpenService(schSCManager,"RealRoadInfo",SERVICE_ALL_ACCESS);
if (NULL != schService)
{
if (TRUE == ::ControlService(schService,SERVICE_CONTROL_STOP, &g_sStatus))
{
while( ::QueryServiceStatus( schService, &g_sStatus) )
{
if (g_sStatus.dwCurrentState == SERVICE_STOP_PENDING )
{
::Sleep( 1000 );
}
else
{
break;
}
}
if (g_sStatus.dwCurrentState == SERVICE_STOPPED )
{
WriteDebug("RealRoadInfo Stop \n");
printf("RealRoadInfo Stop \n");
bRet = TRUE;
}
else
{
WriteDebug("RealRoadInfo failed \n");
printf("RealRoadInfo failed \n");
bRet = FALSE;
}
}
// now remove the service
if( TRUE == ::DeleteService(schService) )
{
WriteDebug("RealRoadInfo removed \n");
printf("RealRoadInfo removed \n");
bRet = TRUE;
}
else
{
WriteDebug("RealRoadInfo DeleteService failed \n");
printf("RealRoadInfo DeleteService failed \n");
bRet = FALSE;
}
::CloseServiceHandle(schService);
}
else
{
WriteDebug("RealRoadInfo OpenService failed \n");
printf("RealRoadInfo OpenService failed \n");
bRet = FALSE;
}
::CloseServiceHandle(schSCManager);
}
else
{
WriteDebug("RealRoadInfo OpenSCManager failed \n");
printf("RealRoadInfo OpenSCManager failed \n");
bRet = FALSE;
}
return bRet;
}
int main(int argc, char *argv[])
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{"RealRoadInfo",(LPSERVICE_MAIN_FUNCTION)ServiceMainFn}, {NULL,NULL}
};
if ( (argc > 1) &&
((*argv[1] == '-') || (*argv[1] == '/')) )
{
if ( _stricmp( "install", argv[1]+1 ) == 0 )
{
InstallService();
}
else if ( _stricmp( "remove", argv[1]+1 ) == 0 )
{
RemoveService();
}
else
{
goto dispatch;
}
::exit(0);
}
// if it doesn't match any of the above parameters
// the main control manager may be starting the main
// so we must call StartServiceCtrlDispatcher
dispatch:
// this is just to be friendly
printf( "%s -install to install the main\n", "RealRoadInfo" );
printf( "%s -remove to remove the main\n", "RealRoadInfo" );
printf( "\nStartServiceCtrlDispatcher being called.\n" );
printf( "This may take several seconds. Please wait.\n" );
if (!StartServiceCtrlDispatcher(dispatchTable))
{
WriteDebug("StartServiceCtrlDispatcher failed. \n");
}
return 0;
}
// 서비스의 현재 상태를 변경하는 함수
void MySetStatus(DWORD dwState, DWORD dwAccept = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE)
{
SERVICE_STATUS ss;
ss.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
ss.dwCurrentState=dwState;
ss.dwControlsAccepted=dwAccept;
ss.dwWin32ExitCode=0;
ss.dwServiceSpecificExitCode=0;
ss.dwCheckPoint=0;
ss.dwWaitHint=0;
// 현재 상태를 보관해 둔다.
g_dwNowState = dwState;
SetServiceStatus(g_hSrv,&ss);
}
void ServiceMainFn(DWORD argc, LPTSTR *argv)
{
// 서비스 핸들러를 등록한다.
WriteDebug("서비스 시작\n");
g_hSrv = RegisterServiceCtrlHandler("RealRoadInfo",(LPHANDLER_FUNCTION)ServiceHandlerFn);
if (g_hSrv == 0)
{
return;
}
// 서비스가 시작중임을 알린다.
MySetStatus(SERVICE_START_PENDING);
g_hExitEvent = CreateEvent(0, FALSE, FALSE, 0);
ResetEvent(g_hExitEvent);
CoInitialize(NULL); // COM 컴퍼넌트를 쓰기위한 라리브러리 초기화 ado를 쓰는 넘이라 이거 넣습니다. 필요 없으면 빼셔두
AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0); //MFC를 쓰기 위한 초기화
CRealMgr * pCRM = new CRealMgr; //제 메인 프로세스 스레드로 동작구동만 시키면 동작 합니다.
WriteDebug("시작 통보\n");
// 서비스가 시작되었음을 알린다.
MySetStatus(SERVICE_RUNNING);
while(1)
{
DWORD dwRet = WaitForMultipleObjects(1, &g_hExitEvent , FALSE, INFINITE); //메인 프로세스가 알아서 하기 때문에 서비스는 정지
if (dwRet == WAIT_FAILED)
{
continue;
}
else if (dwRet == WAIT_TIMEOUT)
{
continue;
}
WriteDebug("서비스 종료\n");
break;
}
delete pCRM;
CoUninitialize();
CloseHandle(g_hExitEvent);
MySetStatus(SERVICE_STOPPED);
}
// 핸들러 함수
void ServiceHandlerFn(DWORD fdwControl)
{
// 현재 상태와 같은 제어 코드일 경우는 처리할 필요 없다.
if (fdwControl == g_dwNowState)return;
switch (fdwControl)
{
case SERVICE_CONTROL_STOP:
MySetStatus(SERVICE_STOP_PENDING,0);
SetEvent(g_hExitEvent); //서비스 프로세스를 시그널 시켜 줍니다.
WriteDebug("종료 메세지\n");
break;
default:
MySetStatus(g_dwNowState);
break;
}
}
'글 > 코딩' 카테고리의 다른 글
eclipse helio에 resin 2.x 버전 물리는 방법 입니다 ^^ (1) | 2011.01.28 |
---|---|
UNICODE 기반에서 SendRequest 할시 방법 입니다 (0) | 2010.05.26 |
현재 메모리에 올라가 있는 프로세스 확인하기 (0) | 2010.01.25 |
BugslayerUtil에 쓰는 파일들 입니다 (0) | 2010.01.25 |
VS2005 이상에서 UTF8 변환 과정 설명입니다 (0) | 2010.01.07 |