如何用VC6.0编写Windows Service程序

来源:互联网 发布:red hat linux虚拟机 编辑:程序博客网 时间:2024/04/30 12:30

如何用VC6.0编写Windows Service程序

2005/10/11

杨登峰(MSN:dengfengyang@hotmail.com)

本人在项目开发要用到创建Service应用程序。但是网络好像这方面具体说明的文章还是比较少。大多都是.Net架构下如何使用基础类来写Windows Service程序。看了以后,我感觉很不能说明Windows Service应用程序的特点。

我在参考MSDN后,觉得还是有必要把Windows Service接口大概架构说明一下,免得以后的人还要从头看MSDN。不当之处还请指出。

主要就是涉及到Service Control Manager(SCM)。SCM主要就是管理Service对象的。因为Service为系统托管结构的一种应用程序,所以每个Service都对应一个内核对象。通过CreateService和OpenService函数创建与删除。系统内部有一个Service对象与Service处理函数的映射表。这样系统就可以托管Service程序了。而Service处理函数也就是Service应用程序的关键的提供给系统的回调函数。在Service程序中,比较主要的就是一开始必须要调StartServiceCtrlDispatcher函数,使SCM知道Service程序的消息响应处理函数。

(1)创建服务

首先调用OpenSCManager(),与计算机操作系统的服务控制管理器连接,并且打开系统的服务控制管理器数据库。
    schSCManager = OpenSCManager(
                        NULL,                   // machine (NULL == local)
                        NULL,                   // database (NULL == default)
                        SC_MANAGER_ALL_ACCESS   // access required
                        );

通过调用函数CreateService(),打开一个服务对象。并且把此服务对象添加到系统的服务控制管理器数据库中。
        schService = CreateService(
            schSCManager,               // SCManager database
            TEXT(SZSERVICENAME),        // name of service
            TEXT(SZSERVICEDISPLAYNAME), // 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
            szPath,                     // service's binary
            NULL,                       // no load ordering group
            NULL,                       // no tag identifier
            TEXT(SZDEPENDENCIES), // dependencies
            NULL,                       // LocalSystem account
            NULL);                      // no password

定义服务应用程序的主进入点函数。当创建的服务运行时,此函数就是服务主要功能的体现。
 SERVICE_TABLE_ENTRY dispatchTable[]//service dispatchTable
 =
 {
  { TEXT((LPTSTR)(LPCTSTR)SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main },// 这里的service_main就是服务应用程序的主进入点函数。
  { NULL, NULL }//
 };

调用函数StartServiceCtrlDispatcher(),制定创建服务的回调函数,把此回调函数挂接到服务控制管理器中。这样服务就可以通过回调函数来实现消息派送。
void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
{
    //×¢2áservice_ctrl£?(scm->service ????oˉêy)
    sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);
    if (!sshStatusHandle)
        goto cleanup;


    //服务功能性代码。
   

    return;
}
在函数service_main中,首先要服务控制管理器的请求接口赋予一个回调函数指针,完成用户在服务控制管理器中点击“开始”,“暂停”,“继续运行”以及“停止”等等消息响应。
 sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);//挂接系统服务控制管理器的响应的回调函数接口。
VOID WINAPI service_ctrl(DWORD dwCtrlCode)
{
    // Handle the requested control code.
    //
    switch(dwCtrlCode)
    {
        // Stop the service.
        //
        // SERVICE_STOP_PENDING should be reported before
        // setting the Stop Event - hServerStopEvent - in
        // ServiceStop().  This avoids a race condition
        // which may result in a 1053 - The Service did not respond...
        // error.
        case SERVICE_CONTROL_STOP:
            ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
            stopService();
            return;

        // Update the service status.
        //
        case SERVICE_CONTROL_INTERROGATE:
            break;

        // invalid control code
        //
        default:
            break;

    }

    ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
}


(2)卸载服务
打开OpenSCManager() 服务控制管理器
调用OpenService()根据服务名字,打开对应服务,并返回相应的句柄。
先关闭要卸载的服务。
ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus );

通过QueryServiceStatus()函数确认此服务已经关闭。
                while( QueryServiceStatus( schService, &ssStatus ) )
                {
                    if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
                    {
                        _tprintf(TEXT("."));
                        Sleep( 1000 );
                    }
                    else
                        break;
                }

通过DeleteService来删除此服务。
            if( DeleteService(schService) )


Demo程序( http://www.metalsoft.cn/article/WindowService.rar )

原创粉丝点击