C++快速编写 windows 服务程序调用程序
2012-07-19 23:42:22| 分类:C/C++ | 标签:windows 服务程序 c++ 快速简单 |字号 订阅
前不久 , 为完成项目中某个功能 , 需要写个 windows 服务程序 , 定时来调用另外的一个 exe 程序 , 完成过程遇到颇多问题 , 作为初学者 , 分享一下我的整个过程 . 参考了多位大神的文章 . 资料来自网上 , 最后给出链接 . 表示感谢
以下是一些基本知识 , 不得不耐下心去理解 , 这对程序理解和编写非常用帮助 . 首先 Microsoft Windows 服务(即,以前的 NT 服务使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动, 可以暂停和重新启动而且不显示任何用户界面。 这使服务非常适合在服务器上使用, 或任何 时候, 为了不影响在同一台计算机上工作的其他用户, 需要长时间运行功能时使用。 还可以 在不同于登录用户的特定用户帐户或默认计算机帐户的安全上下文中运行服务。
服务是有状态的, 当我们使用 windows 自带的服务管理程序 sc.exe 查看服务状态时可以显 示服务的当前状态, 这个状态是由我们在程序代码中进行控制的。 你最好在服务初始化的时 候将服务设置为 SERVICE_START_PENDING,当初始化完毕时设为
SERVICE_RUNNING,这些状
态是系统自定义的状态, 可通过 msdn 查看其他状态。 这个状态信息你会在 sc.exe 中看到。
在编写 windows 服务程序过程中你需要关注的函数有:
1. 首先是 main 函数, 由于 windows 服务不需要界面, 所以大部分程序为 win32控制台应用 程序,所以程序主函数为 main 而不是 WinMain(。在主函数要做的主要工作就是初始化一 个 SERVICE_TABLE_ENTRY 分派表结构体, 然后调用
StartServiceCtrlDispatcher(;这将 把调用进程的主线程转换为控制分派器。 该分派器启动一个新线程, 该线程运行分派表中对 应于你的服务的 ServiceMain (函数。 ServiceMain (函数将在下面提到。
此过程示例代码如下:
SERVICE_TABLE_ENTRY entrytable[2]; entrytable[0].lpServiceName=\
entrytable[0].lpServiceProc=(LPSERVICE_MAIN_FUNCTIONServiceMain; entrytable[1].lpServiceName=NULL; entrytable[1].lpServiceProc=NULL; StartServiceCtrlDispatcher(entrytable;
在这之后系统将自动创建一个线程去执行 ServiceMain 函数的内容, 你应该将你要执行的任 务
在 ServiceMain 中循环,这样服务就开始运行了。
2. ServiceMain 函数为 void WINAPI ServiceMain(int argc, char** argv格式的函数,函 数名字可以任意定义。 它的作用就是:将你需要执行的任务放到该函数中循环执行即可。 这 就是服务程序的工作函数。在 ServiceMain 执行你的任务前,需要给
SERVICE_TABLE_ENTRY 分派
表结构体进行赋值, 注意由于此时服务还没有开始执行你的任务所以我们将服务的状态设置 为 SERVICE_START_PENDING,即正在初始化。我们进行如下赋值: servicestatus.dwServiceType = SERVICE_WIN32;
servicestatus.dwCurrentState = SERVICE_START_PENDING;
servicestatus.dwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCE PT_STOP;
//在本例中只接受系统关机和停止服务两种控制命令 servicestatus.dwWin32ExitCode = 0; servicestatus.dwServiceSpecificExitCode = 0; servicestatus.dwCheckPoint = 0; servicestatus.dwWaitHint = 0;
hstatus = ::RegisterServiceCtrlHandler(\
CtrlHandler 为 void WINAPI CtrlHandler(DWORD request型的函数,函数名字可以任意设 定。将在下一点讲到。
Hstatus 为 SERVICE_STATUS_HANDLE 类 型 的 全 局 变 量 。 当 需 要 改 变 服 务 状 态 时 SetServiceStatus (函数需要它做为参数来标识一个服务。
3. void WINAPI CtrlHandler(DWORD request,函数的主要功能是,接收系统传递的控制 命令, 比如当你通过 sc.exe 关闭服务时, 该函数会收到
SERVICE_CONTROL_STOP消息, 你就可以对服务进行必要的管理。在本例子程序中就只接收
SERVICE_ACCEPT_SHUTDOWN 和
SERVICE_ACCEPT_STOP消息,这是通过前面给 servicestatus 赋值设定的。 这样一个 基本的服务程序就完成了。 本文结束的时候会附上如
何安装服务。