서비스를 설치 하고, 제거 할 수 있으며 서비스를 시작하면 1초마다 윈도우즈 기본 에러메시지.. ~ 이 나옵니다.
서비스를 일시 중지 시키면 동작이 멈추고, 재시작하면 다시 띵~ 이러한 구조로 흘러갑니다.
간단하게 util.h util.cpp 를 만들어서 구조와 크게 상관없는 함수들을 모아놓았습니다.

#include "util.h"
#pragma comment(lib, "Advapi32.lib")

const char* S_NAME = "TEST";
const char* S_DISP   = "TEST Service";
const char* S_DESC  = "TEST Service Description"; 

// 서비스를 제어하기 위한 핸들을 저장하고 있어야한다.
SERVICE_STATUS_HANDLE srvhd = 0;

// 서비스의 상태를 저장하는 플래그
DWORD  srvst = SERVICE_STOPPED;

int main(int argc, char** argv)
{
    // 실행파일의 경로를 구한다.
    char S_BINARY[MAX_PATH] = {0};
    ::GetModuleFileName(NULL, S_BINARY, MAX_PATH);

    // 인자가 2개이고, 두번째 인자가 'i' 이면 인스톨
    if(argc == 2 && argv[1][0] == 'i')
    {
        ServiceInstall();
        return 0;
    }

    // 인자가 2개이고, 두번째 인자가 'u' 이면 언인스톨
    else if(argc == 2 && argv[1][0] == 'u')
    {
        ServiceUninstall();
        return 0;
    }

    SERVICE_TABLE_ENTRY STE[] =   
    {
        {(char*)S_NAME, (LPSERVICE_MAIN_FUNCTION)_tmain_service},
        {NULL,NULL}
    };
    // 서비스 메인 함수를 등록한다.
    if(StartServiceCtrlDispatcher(STE) == FALSE)
        return -1;

    return 0;
}

 VOID _tmain_service(INT ARGC, LPSTR* ARGV)
{
    srvhd = RegisterServiceCtrlHandlerEx(S_NAME, _tmain_service_handler, NULL);
    if (srvhd == NULL)
        return;       

    // 정상적으로 서비스가 시작되었다.
    // 서비스의 기본적인 작업이 끝나고 메인 루프로 들어가기 전에 꼭 상태를
    // 런닝 상태로 만들어주어야 한다
    // 이걸 처리해놓지 않으면, 서비스 관리자에서 정상적으로 시작된건을 인지하지 못한다.
    SET_SERVICE_STATE(srvhd, SERVICE_RUNNING);

    // 무한 루프를 돌면서 띵띵~ 소리를 낸다.
    while(GET_SERVICE_STATE() != SERVICE_STOPPED)
    {
        // 일시 중지 상태일 때는 그냥 별동작 없이 대기를 반복한다.
        if(GET_SERVICE_STATE() == SERVICE_PAUSED)
        {
            Sleep(1000);
            continue;
        }

        ::MessageBeep(0xFFFFFFFF);
        Sleep(1000);
    }
    return;
}

DWORD WINAPI _tmain_service_handler(DWORD fdwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
    // 서비스라 좋은점이 있네, 시스템에서 발생하는 잡다구리한 이벤트들을 별로 힘들이지 않고
    // 이곳에서 받아다가 처리할 수 있다.

    switch (fdwControl)
    {
    case SERVICE_CONTROL_PAUSE:
        SET_SERVICE_STATE(srvhd, SERVICE_PAUSE_PENDING,0);
        // 서비스를 일시 중지 시킨다.
        SET_SERVICE_STATE(srvhd, SERVICE_PAUSED);
        break;

    case SERVICE_CONTROL_CONTINUE:
        SET_SERVICE_STATE(srvhd, SERVICE_CONTINUE_PENDING,0);
        // 일시 중지 시킨 서비스를 재개한다.
        SET_SERVICE_STATE(srvhd, SERVICE_RUNNING);
        break;

    case SERVICE_CONTROL_STOP:
        SET_SERVICE_STATE(srvhd, SERVICE_STOP_PENDING, 0);
        // 서비스를 멈춘다 (, 종료와 같은 의미)
        SET_SERVICE_STATE(srvhd, SERVICE_STOPPED);
        break;     

    default:
        break;
    }

    return NO_ERROR;
}

// 아래 파일은 샘플 프로젝트입니다.

TestService.zip
0.01MB


다음에는 개인용 피씨나, 서버 피씨에 어떤 사용자가 접속하고, 종료했는지 터미널 서버로 들어왔다면
어떤 IP주소로 접속했는지 등등등.. '내컴퓨터 누가 건드렸어..' 서비스를 만들어 보도록 하겠습니다.

출처: https://crowback.tistory.com/184?category=86281 [까막's 블로그:티스토리]

+ Recent posts