码迷,mamicode.com
首页 > Windows程序 > 详细

WIN32服务程序(三):完整的服务程序实例

时间:2016-01-01 16:54:28      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:

前面我们所讲的“服务程序”,更准确地说是服务控制程序,例如我们通过输入应用的路径,将一个应用程序添加到服务控制管理器。一个服务控制程序可以将一个程序添加到服务控制管理器中,并控制它的运行、停止和删除等。那么怎么避免手动添加的方式,直接将我们想要运行的代码添加到服务中呢?这需要我们建立一个完整的服务程序,要同时包括服务主程序和服务控制程序。

关于服务主程序

服务主程序包括一个main函数作为程序的标准入口,一个ServiceMain函数作为服务程序的入口,一个Handler函数实现服务启动,停止等功能,最后是一个MyWork函数,这里面可以写入我们想要运行的代码,也就是服务要实现的功能。

我们来看一个程序,该程序实现的功能是在服务运行期间,循环执行MessageBox函数;可以在cmd上运行应用程序,给其传递参数,实现对于服务的控制。这个程序在逻辑的实现上比较简单,某些函数可以直接查看msdn文档,附上链接地址https://technet.microsoft.com/zh-cn/library/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsvc.h>
#include <stdio.h>

#define SLEEP_TIME 5000
#define LOG_FILE "c:\\MemoryWatch.txt"
#define SERVICE_NAME    "servitest"
#define SERVICE_DESC    "test"
#define SERVICE_DISPLAY_NAME "test"

SERVICE_STATUS    ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
SC_HANDLE scm;
SC_HANDLE scv;

void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
void Log(char* filename);
int startFunc();
void OnStart();
void OnCreate();
void OnDelete();
void OnStop();

int main(int argc, char* argv[])
{
    // Service Name:MemoryStatus
    // Service Handle Function: ServiceMain()
    SERVICE_TABLE_ENTRY ServiceTable[2] =
    {

        { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },

        { NULL,NULL}
    };

    if(argc == 2)
    {  
        if(!stricmp(argv[1],"-create"))
        {
            OnCreate();
            return 0;
        }
        else if(!stricmp(argv[1],"-delete"))
        {
            OnDelete();
            return 0;
        }
        else if(!stricmp(argv[1],"-start"))
        {
            OnStart();
            return 0;
        }
        else if(!stricmp(argv[1],"-stop"))
        {
            OnStop();
            return 0;
        }  
        else
        {
            printf("invailid parameter\n");
            return 0;
        }
    }


    StartServiceCtrlDispatcher(ServiceTable);
    return 0;
}

void Log(char* str)
{
    FILE* fp = fopen(LOG_FILE, "a+");
    if(fp == NULL)
    {
        printf("error to open file: %d\n", GetLastError());
        return;
    }
    
    fprintf(fp, "%s\n", str);
    fflush(fp);
    fclose(fp);
}

void ServiceMain(int argc, char** argv)
{
    BOOL bRet;
    int result;

    bRet = TRUE;

    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCheckPoint   = 0;
    ServiceStatus.dwWaitHint   = 0;
    ServiceStatus.dwServiceType   = SERVICE_WIN32;
    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    ServiceStatus.dwServiceSpecificExitCode = 0;

    hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)ControlHandler);
    if(hStatus == (SERVICE_STATUS_HANDLE)0)
    {
        // log failed
        return;
    }
    //service status update
    ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(hStatus, &ServiceStatus);

    while(ServiceStatus.dwCurrentState == SERVICE_RUNNING)
    {
        result = startFunc();
        if(result)
        {
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            ServiceStatus.dwWin32ExitCode = -1;
            SetServiceStatus(hStatus, &ServiceStatus);
            return;
        }
    }
}

int startFunc()
{
    MessageBox(NULL, "startFunc", SERVICE_NAME, MB_OK);
    return 0;
}

void ControlHandler(DWORD request)
{
    switch(request)
    {
        case SERVICE_CONTROL_STOP:
            Log("Monitoring stopped.");
            ServiceStatus.dwWin32ExitCode = 0;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus (hStatus, &ServiceStatus);
            return;

        case SERVICE_CONTROL_SHUTDOWN:
            Log("Monitoring stopped.");
            ServiceStatus.dwWin32ExitCode = 0;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus (hStatus, &ServiceStatus);
            return;
        default:
            break;
    }

    SetServiceStatus (hStatus, &ServiceStatus);
}

void OnCreate()
{
    char filename[MAX_PATH];
    DWORD dwErrorCode;
    GetModuleFileName(NULL, filename, MAX_PATH);
    printf("Creating Service .... ");
    scm = OpenSCManager(0/*localhost*/,
                        NULL/*SERVICES_ACTIVE_DATABASE*/,
                        SC_MANAGER_ALL_ACCESS/*ACCESS*/);
    if (scm == NULL)
    {
        printf("OpenSCManager error:%d\n", GetLastError());
        return;
    }
    scv = CreateService(scm,//句柄
    SERVICE_NAME,//服务开始名
    SERVICE_DISPLAY_NAME,//显示服务名
    SERVICE_ALL_ACCESS, //服务访问类型
    SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,//服务类型
    SERVICE_AUTO_START, //自动启动服务
    SERVICE_ERROR_IGNORE,//忽略错误
    filename,//启动的文件名
    NULL,//name of load ordering group (载入组名)
    NULL,//标签标识符
    NULL,//相关性数组名
    NULL,//帐户(当前)
    NULL); //密码(当前)

    if (scv == NULL)
    {
        dwErrorCode = GetLastError();
        if(dwErrorCode!=ERROR_SERVICE_EXISTS)
        {
            printf("Failure !\n");
            CloseServiceHandle(scm);
            return ;
        }
        else
        {
            printf("already Exists !\n");
        }
    }
    else
    {
        printf("Success !\n");
        CloseServiceHandle(scv);

    }

    CloseServiceHandle(scm);
    scm = scv = NULL;
}

void OnDelete()
{
    scm=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if (scm!=NULL)
    {
        scv=OpenService(scm,SERVICE_NAME,SERVICE_ALL_ACCESS);
        if (scv != NULL)
        {
            QueryServiceStatus(scv,&ServiceStatus);
            if (ServiceStatus.dwCurrentState==SERVICE_RUNNING)
            {
                ControlService(scv,SERVICE_CONTROL_STOP,&ServiceStatus);
            }
        DeleteService(scv);
        CloseServiceHandle(scv);
        }
    CloseServiceHandle(scm);
    }
    scm = scv = NULL;
}


void OnStart()
{
    DWORD dwErrorCode;
    //Starting Service
    printf("Starting Service .... ");
    scm = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if(scm != NULL)
    {
        scv = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS);
        if (scv != NULL)
        {
            if(StartService(scv, 0, NULL)==0)                        
            {
                dwErrorCode = GetLastError();
                if(dwErrorCode == ERROR_SERVICE_ALREADY_RUNNING)
                {
                    printf("already Running !\n");
                    CloseServiceHandle(scv);
                    CloseServiceHandle(scm);
                    return ;
                }
            }
        else
        {
            printf("Pending ... ");
        }

        //wait until the servics started
        while(QueryServiceStatus(scv,&ServiceStatus)!=0)          
        {
            if(ServiceStatus.dwCurrentState == SERVICE_START_PENDING)
            {
                Sleep(100);

            }
            else
            {
                break;

            }
        }

        CloseServiceHandle(scv);
        }
        else
        {
            //error to OpenService
            printf("error to OpenService\n");
        }

        CloseServiceHandle(scm);
    }
    else
    {
        //fail to OpenSCManager
    }
    /*
    if(InstallServiceStatus.dwCurrentState != SERVICE_RUNNING)
    {
        printf("Failure !\n");                      
    }
    else
    {
        printf("Success !\nDumping Description to Registry...\n");  
        RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        "SYSTEM\\CurrentControlSet\\Services\\NtBoot",
        0,
        KEY_ALL_ACCESS,
        &hkResult);
        RegSetValueEx(hkResult,
        "Description",
        0,
        REG_SZ,
        (unsigned char *)"Driver Booting Service",
        23);

        RegCloseKey(hkResult);
    }

    CloseServiceHandle(schSCManager);
    CloseServiceHandle(schService);
    }//
    */

    scm = scv = NULL;
}


void OnStop()
{
    scm = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    if(scm != NULL)
    {
        scv = OpenService(scm,SERVICE_NAME,SERVICE_STOP | SERVICE_QUERY_STATUS);
        if (scv!=NULL)
        {
            QueryServiceStatus(scv,&ServiceStatus);
            if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
            {
                ControlService(scv,SERVICE_CONTROL_STOP,&ServiceStatus);
            }
            CloseServiceHandle(scv);
        }
        CloseServiceHandle(scm);
    }
    scm = scv = NULL;
}

程序编译好之后,运行cmd。我编译好的程序的完整路径是 C:\hi\Debug\hi.exe 

执行 C:\hi\Debug\hi.exe -create创建服务

执行C:\hi\Debug\hi.exe  -start 启动服务

……

在c盘MemoryWatch.txt有日志文件

 

WIN32服务程序(三):完整的服务程序实例

标签:

原文地址:http://www.cnblogs.com/lanf/p/5093439.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!