VC编写系统服务程序笔记
2012-08-24 13:21
399 查看
这里我要把自己写好的程序设置为开机启动了,所以注册为服务程序是最好的方法,先看VC写服务程序的思路
服务程序通常编写成控制台类型的应用程序,总的来说,一个遵守服务控制管理程序接口要求的程序包含下面三个函数:
1.服务程序主函数(main):调用系统函数 StartServiceCtrlDispatcher 连接程序主线程到服务控制管理程序
StartServiceCtrlDispatcher 函数有一个 SERVICE_TABLE_ENTRY 作为参数,里面指定了 Service 的名字和入口点。 如果 StartServiceCtrlDispatcher 函数调用成功,被调用线程不会在 Service 进程结束以前返回。
SERVICE_TABLE_ENTRY 结构具体描述如下:
2.服务入口点函数(ServiceMain):执行服务初始化任务,同时执行多个服务的服务进程有多个服务入口函数
标准的ServiceMain 函数需要执行以下任务:
1.马上调用 RegisterServiceCtrlHandlerEx 去注册一个 处理函数(HandlerEx) 去处理 Service 的 控制要求。返回值是通知 SCM 的 Service 状态处理的 Handle
2.执行初始化单元,如果初始化代码的执行时间少于1秒或很短,可以在 ServiceMain 里执行,如果 初始化时间很长,最好先调用 SetServiceStatus 函数,指定状态为 SERVICE_START_PENDING (启动中)。
如果初始化时间超过30秒,就必须建立另外的线程完成这些共同的初始化工作,从而保证服务程序主函数能及时地调用 StartServiceCtrlDispatcher 函数
如果 初始化 或 运行 过程中出现了错误,应该调用 SetServiceStatus 并指定 SERVICE_STOP_PENDING(正在停止) 。完成清场工作后,再指定现在状态为 SERVICE_STOPPED, 记得在 SERVICE_STATUS 结构中指定成员 dwServiceSpecificExitCode 和 dwWin32ExitCode 的值,用来指定错误的类型。
3.控制服务处理程序函数(Handler):在服务程序收到控制请求时由控制分发线程引用。
当SCM发出控制请求的时候,控制处理函数必须在30秒内返回,否则 SCM 会返回错误。
好了,思路有了,下面是每个步骤详细的写法,这里有现成的说明我就不自己写了:http://www.vckbase.com/index.php/wv/1193
另附服务应用程序详细介绍:http://blog.csdn.net/showna/article/details/1543517
我写的源码,东拼西凑的,不对的地方希望能指出啊:
http://blog.csdn.net/pgshow/article/details/7677583
这里我要把自己写好的程序设置为开机启动了,所以注册为服务程序是最好的方法,先看VC写服务程序的思路
服务程序通常编写成控制台类型的应用程序,总的来说,一个遵守服务控制管理程序接口要求的程序包含下面三个函数:
1.服务程序主函数(main):调用系统函数 StartServiceCtrlDispatcher 连接程序主线程到服务控制管理程序
StartServiceCtrlDispatcher 函数有一个 SERVICE_TABLE_ENTRY 作为参数,里面指定了 Service 的名字和入口点。 如果 StartServiceCtrlDispatcher 函数调用成功,被调用线程不会在 Service 进程结束以前返回。
SERVICE_TABLE_ENTRY 结构具体描述如下:
typedef struct _SERVICE_TABLE_ENTRY { LPTSTR lpServiceName; //一个以 NULL 结尾的字符串,标识服务名,如果是 SERVICE_WIN32_OWN_PROCESS 类型的服务,这个字符串会被忽略 LPSERVICE_MAIN_FUNCTION lpServiceProc; //指向服务入口点函数 } SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;
2.服务入口点函数(ServiceMain):执行服务初始化任务,同时执行多个服务的服务进程有多个服务入口函数
标准的ServiceMain 函数需要执行以下任务:
1.马上调用 RegisterServiceCtrlHandlerEx 去注册一个 处理函数(HandlerEx) 去处理 Service 的 控制要求。返回值是通知 SCM 的 Service 状态处理的 Handle
2.执行初始化单元,如果初始化代码的执行时间少于1秒或很短,可以在 ServiceMain 里执行,如果 初始化时间很长,最好先调用 SetServiceStatus 函数,指定状态为 SERVICE_START_PENDING (启动中)。
如果初始化时间超过30秒,就必须建立另外的线程完成这些共同的初始化工作,从而保证服务程序主函数能及时地调用 StartServiceCtrlDispatcher 函数
如果 初始化 或 运行 过程中出现了错误,应该调用 SetServiceStatus 并指定 SERVICE_STOP_PENDING(正在停止) 。完成清场工作后,再指定现在状态为 SERVICE_STOPPED, 记得在 SERVICE_STATUS 结构中指定成员 dwServiceSpecificExitCode 和 dwWin32ExitCode 的值,用来指定错误的类型。
3.控制服务处理程序函数(Handler):在服务程序收到控制请求时由控制分发线程引用。
当SCM发出控制请求的时候,控制处理函数必须在30秒内返回,否则 SCM 会返回错误。
好了,思路有了,下面是每个步骤详细的写法,这里有现成的说明我就不自己写了:http://www.vckbase.com/index.php/wv/1193
另附服务应用程序详细介绍:http://blog.csdn.net/showna/article/details/1543517
我写的源码,东拼西凑的,不对的地方希望能指出啊:
// Services_test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "Windows.h" //全局变量 SERVICE_STATUS MyServiceStatus; SERVICE_STATUS_HANDLE MyServiceStatusHandle; TCHAR szServiceName[] = TEXT("ServiceTest"); DWORD i = 0; //向前声明 void WINAPI ServiceMain(DWORD argc, LPTSTR *argv); //服务主函数 void WINAPI ControlHandler(DWORD dwMsg); //服务控制函数 int InitService(); //服务初始化函数 int _tmain(int argc, _TCHAR* argv[]) { //初始化一个分配表 SERVICE_TABLE_ENTRY ServiceTable[] = { { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain }, { NULL, NULL } //分派表的最后一项必须是服务名和服务主函数域的 NULL 指针,所以这两项为NULL }; if(!StartServiceCtrlDispatcher(ServiceTable)) // 启动服务的控制分派机线程 { OutputDebugString(TEXT("分派机启动服务失败!")); } return 0; } void WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { int error; //指定服务特征和其当前状态 MyServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; //服务类型 MyServiceStatus.dwCurrentState = SERVICE_START_PENDING; //指定服务的当前状态 MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; //这个成员表示哪些控制通执服务是可接受的 MyServiceStatus.dwWin32ExitCode = 0; //这两个域在你终止服务并报告退出细节时很有用。 MyServiceStatus.dwServiceSpecificExitCode = 0; //初始化服务时并不退出,因此,它们的值为0 MyServiceStatus.dwCheckPoint = 0; //这二个成员允许 MyServiceStatus.dwWaitHint = 0; //一个服务回报它的进度 //注册服务控制 MyServiceStatusHandle = RegisterServiceCtrlHandler(szServiceName, ControlHandler); if (NULL == MyServiceStatusHandle) { //注册失败就返回 OutputDebugString(TEXT("注册服务失败!")); return; } error = InitService(); //初始化数据 if (error) { // 初始化失败,终止服务 MyServiceStatus.dwCurrentState = SERVICE_STOPPED; MyServiceStatus.dwWin32ExitCode = -1; SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus); //向 SCM 报告服务的状态 return; // 退出 ServiceMain } // 如果初始化成功,向 SCM 报告运行状态 MyServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus); while (MyServiceStatus.dwCurrentState == SERVICE_RUNNING) { //这里放你要实现的功能函数 if(i != 100) return; MessageBeep(0); Sleep(3000); } return; } int InitService() { //获取系统目录地址,失败就返回-1 i = 100; return 0; } void WINAPI ControlHandler(DWORD dwMsg) { switch(dwMsg) { case SERVICE_CONTROL_STOP: //响应停止服务控制 MyServiceStatus.dwWin32ExitCode = 0; MyServiceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus); return; default: break; } //向 SCM 报告服务的状态 SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus); return; }
http://blog.csdn.net/pgshow/article/details/7677583
相关文章推荐
- VC编写系统服务程序笔记
- VC实现系统热键激活后台服务程序
- vc编写系统服务
- 服务程序C#编写系统服务,注册表读写问题
- VC系统服务程序
- Windows下编写系统服务程序的实例
- 安装Vs2012后,编写Vc++程序找不到系统头文件和导致VS2010工程编译的问题
- 孙鑫VC学习笔记:第十六讲 用异步套接字编写聊天程序
- Delphi编写系统服务五:在系统服务和桌面程序之间共享内存
- 编写有界面的系统服务程序
- VC实现系统热键激活后台服务程序
- VC编写有图形界面的Windows服务程序
- Delphi编写系统服务四:如何限制系统服务和桌面程序只运行一个
- 关于系统服务程序的编写
- 服务程序C#编写系统服务,注册表读写问题
- 编写有界面的系统服务程序
- Delphi编写系统服务四:如何限制系统服务和桌面程序只运行一个
- VC 服务程序的编写
- Delphi编写系统服务二:系统服务和桌面程序的区别
- 孙鑫vc++ 第七课 笔记 对话框用户界面程序的编写