程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> WIN32服務程序(三):完整的服務程序實例,win32服務程序實例

WIN32服務程序(三):完整的服務程序實例,win32服務程序實例

編輯:關於C語言

WIN32服務程序(三):完整的服務程序實例,win32服務程序實例


前面我們所講的“服務程序”,更准確地說是服務控制程序,例如我們通過輸入應用的路徑,將一個應用程序添加到服務控制管理器。一個服務控制程序可以將一個程序添加到服務控制管理器中,並控制它的運行、停止和刪除等。那麼怎麼避免手動添加的方式,直接將我們想要運行的代碼添加到服務中呢?這需要我們建立一個完整的服務程序,要同時包括服務主程序和服務控制程序。

關於服務主程序

服務主程序包括一個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有日志文件

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved