65.9K
CodeProject 正在变化。 阅读更多。
Home

成为一名服务

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.16/5 (19投票s)

2003 年 4 月 6 日

4分钟阅读

viewsIcon

97448

downloadIcon

2426

本文介绍了一组 C 函数,您可以在您的项目中调用它们,用几行代码编写 Windows 服务。

引言

编写一个服务并非总是易事,特别是当您需要处理大量现有代码时。OSR_Service 工具包是一组 C 文件,您可以将其包含在 C/C++ 项目中,用极少的代码编写 Windows 服务功能。

ServiceStart 函数

ServiceStart 函数启动服务。它可能在应用程序的开始时被调用。
OSR_ERROR OSR_CALL ServiceStart(OSR_SERVICE_PARAMS * Params)

参数

Params

指向 OSR_SEVICE_PARAMS 结构的指针,该结构包含服务启动参数和首选项。

返回值

如果函数成功,则返回值为 OSR_SUCCESS。

备注

理想情况下,此函数应在主函数(WinMain)中调用,然后在服务运行时应用程序可能执行的代码之前。

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,int nCmdShow)
{
     OSR_SERVICE_PARAMS params;
    params.ServiceDependencies[0] = 0;
    params.ServiceDependencies[1] = 0;
    
    strcpy((char *)params.ServiceLogin,".\\Administrateur");
    strcpy((char *)params.ServicePassword,"AdminPassword");
    strcpy((char *)params.ServiceName,"OSR_SAPMPLE_SERVICE");
    strcpy((char *)params.ServiceNameDisplay,"OSR sample service");
    
    params.ServiceAcceptedCommands = SERVICE_ACCEPT_STOP|
                        SERVICE_ACCEPT_PAUSE_CONTINUE|SERVICE_ACCEPT_SHUTDOWN;
    params.ServiceStartType = SERVICE_DEMAND_START;

        
    if(strcmp(lpCmdLine,"install") == 0)
    {
        // Install the service
        //**********************
        ServiceInstall(&params);
    }
    else
    {    
        if(strcmp(lpCmdLine,"uninstall") == 0)
        {
            
            // Uninstall the service
            //**********************
            ServiceUninstall(&params);
        }
        else
        {
        
            // Start the service
            //**********************
            ServiceStart(&params);

            // The service is now running
            //***************************
            while(!stop_request)
            {
                // Do something
                //*******************
                printf("I'm a running service\n");
                Sleep(1000);
            }
        }
    }
        
    return 0;
}

OSR_APP_XXX 函数

用户必须编写四个回调函数来处理服务消息。这些函数是
int OSR_CALL OSR_APP_START(int step);
int OSR_CALL OSR_APP_STOP(int step);
int OSR_CALL OSR_APP_PAUSE(int step);
int OSR_CALL OSR_APP_CONTINUE(int step);
int OSR_CALL OSR_APP_SHUTDOWN(int step);

当服务收到服务管理器发来的消息,请求更改状态(例如,服务正在运行,我们想停止它)时,OSR_APP_STOP 会被调用一次。根据此函数返回的值,该函数将被调用直到停止过程完成。

解释

如图 1 所示,服务有 3 种主要状态(STOPEDRUNNINGPAUSED)和 4 种挂起状态(START PENDINGPAUSE PENDINGCONTINUE PENDINGSTOP PENDING)。


Service states
图 1. 服务状态


主要状态是由服务管理器请求的状态(例如,停止服务),而挂起状态是两种主要状态之间的过渡状态。应用程序以此方式告知服务管理器:“好的!我正在执行停止应用程序所需的操作,请稍候”。

参数

step

step 是一个增量值,在同一状态更改下每次调用函数时发送给该函数。

返回值

函数可以返回 3 个值
含义
OSR_SERVICE_WAIT
初始化过程未完成,服务保持挂起状态,并且将再次调用此函数,step 值会增加。
OSR_SERVICE_DONE
初始化过程已完成。服务可以处于请求的状态。
OSR_SERVICE_ABORT
初始化过程无法完成或失败。无法更改状态。

备注

所有这些函数都必须返回一个结果以允许状态更新。
对于 OSR_APP_START 函数,您可能会启动一个新线程来在启动初始化后运行某些内容。
这是一个简单的 3 步启动过程。
int OSR_CALL OSR_APP_START(int step)
{
    switch(step)
    {
    case 0:
        OpenLogFile();
        return OSR_SERVICE_WAIT
    break;

    case 1:
        InitSocket();
        return OSR_SERVICE_WAIT;
    break;

    case 2:
        return OSR_SERVICE_DONE;
    break;
}

OSR_SERVICE_PARAMS 结构

typedef struct _OSR_SERVICE_PARAMS
{
// Name of the service
UCHAR ServiceName[STR_CHAR32];     
// Service name displayed in the service manager
UCHAR ServiceNameDisplay[STR_CHAR32]; 
// Dependencies name array
UCHAR ServiceDependencies[STR_CHAR64];    
// Service start mode    
U32BIT ServiceStartType;
// Login used by the service                
UCHAR ServiceLogin[STR_CHAR32];            
// Password used by the service
UCHAR ServicePassword[STR_CHAR32];
// Commands you can use with this service            
U32BIT ServiceAcceptedCommands;            
}OSR_SERVICE_PARAMS;

成员

ServiceName

以 null 结尾的字符串,用于命名服务。 "\" 和 "/" 字符在服务名称中无效。

ServiceNameDisplay

以 null 结尾的字符串,用于用户界面程序识别服务。

ServiceDependencies

以 null 结尾的双 null 结尾的字符串数组,其中包含在此服务之前必须启动的服务或加载顺序组的名称。如果不需要依赖项,则指定 NULL。

- "NetworkService\0LogService\0\0" 表示 NetworkService 和 LogService 可以在您的服务启动之前启动。
- "\0\0" 表示未定义依赖项。

ServiceStartType

指定何时启动服务。您必须指定以下启动类型之一
含义
SERVICE_AUTO_START
指定一个服务,该服务在系统启动期间由服务控制管理器自动启动。
SERVICE_DEMAND_START
指定一个服务,该服务在进程调用 StartService 函数时由服务控制管理器启动。
SERVICE_DISABLED 指定一个不再能启动的服务。

ServiceLogin

以 null 结尾的字符串,用于命名服务。您必须使用格式为 DomainName\UserName 的帐户名。由于该帐户属于内置域,因此您可以指定 .\UserName。您还必须指定 LocalSystem 帐户。如果指定空字符串("\0"),则使用 LocalSystem 帐户。

ServicePassword

以 null 结尾的字符串,包含 ServiceLogin 参数指定的帐户的密码。如果字符串为空,则服务没有密码。

使用示例

此项目提供了一个示例项目,演示了如何将 osr_service 代码集成到“实际”代码中。示例代码包含一个预编译的二进制文件 - 适用于 X86 win32 平台 - 其运行方式如下。

sample_service [install|uninstall] 用于将服务安装或从服务管理器中移除。为了方便您,我使用系统帐户构建了它,即第一次尝试无需任何更改。

该示例以及 osr_service 的所有函数基本上都以调试模式运行,该模式使用 OutputDebugString 日志方法记录所有错误。要显示日志,您必须使用类似 DebugView 的工具,该工具来自 SysInternals 公司(www.sysinternals.com)。此工具是免费的。
© . All rights reserved.