Visual Studio 6Visual C++ 7.0Windows 2000Visual C++ 6.0Windows XPIntermediateDevVisual StudioWindowsC++
成为一名服务






3.16/5 (19投票s)
2003 年 4 月 6 日
4分钟阅读

97448

2426
本文介绍了一组 C 函数,
引言
编写一个服务并非总是易事,特别是当您需要处理大量现有代码时。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(¶ms); } else { if(strcmp(lpCmdLine,"uninstall") == 0) { // Uninstall the service //********************** ServiceUninstall(¶ms); } else { // Start the service //********************** ServiceStart(¶ms); // 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 种主要状态(STOPED
、RUNNING
、PAUSED
)和 4 种挂起状态(START PENDING
、PAUSE PENDING
、CONTINUE PENDING
、STOP PENDING
)。
图 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)。此工具是免费的。