用 ATL 编写 Windows 服务

转载 2007年09月18日 21:50:00

下载源代码

有时候,我们需要自己写的程序在没有用户登陆的情况下,只要Windows系统启动就运行,那我们可以把我们的程序写成一个Windows服务。
  服务是能够为各种用户(包括本地用户和远程用户)所用的,拥有用户授权级进行管理的能力,并且不论用户是否物理的与正在运行该应用程序的计算机相连都能正常执行。
下面,我将用一个简单的例子说明如何用ATL来编写Windows服务程序。
首先,我们新建一个Project。如图一所示,选择 "ATL COM AppWizard",工程名为:ServiceDemo。


图一

点击 "OK ", 出现图二,选择Service [EXE]。点击 Finish。


图二

  完成以上的步骤,一个"什么也不做"的服务就完成了!编译… 打开"控制面板"->"管理工具"
->"服务",嗯?我们写的服务怎么没有在服务管理器(service control manager ,简称(SCM))里面列出来呢?呵呵,被我骗了?不要着急,我们还需要做一些工作。

首先先大概介绍一下向导为我们生成的代码:

  程序的进入点是全局函数_tWinMain, 仔细看一下这个函数,我们会发现当我们运行程序时,可以加上参数,例如: ServiceDemo /RegServer 或者 ServiceDemo -RegServer,这个是用来本地服务器注册(Register as Local S Register as Service erver); ServiceDemo / Service 或者 ServiceDemo -Service,这个是服务的注册(Register as Service);ServiceDemo /UnRegServer 或者 ServiceDemo -UnRegServer ,这个是服务的删除。所以,当我们写好了服务程序,只要运行的时候加上参数 Service ,这个时候在SCM中就会看到我们的服务了。可以试一下在SCM中对这个什么也不做的服务"启动","停止",改变一下它的启动方式。
  每次编码后测试都要在命令行中加参数运行服务才可以在SCM中列出来是不是很麻烦呢?我再介绍一个偷懒的方法,选择VC IDE的菜单Project -> Setting, 再选择Custom Build 面板,如图三:


图三

在"$(TargetPath)" /RegServer的下面加上:"$(TargetPath)" /Service,这样当我们每次编码后编译程序,就不用再在命令行中去加参数执行我们的服务程序完成服务的注册了。
继续介绍向导生成的代码:向导为我们建立了一个类:CServiceModule,全局变量_Module就是这个类的实例。
Init():这个函数用于完成一些初始化工作;
Run():这个函数就是服务开始运行后的内容,我们接下来要修改的内容也就是从这里入手。
Install():
看一下Install()的这一部分:  

SC_HANDLE hService = ::CreateService(hSCM, 
                 m_szServiceName, 
                 m_szServiceName,SERVICE_ALL_ACCESS, 
                 SERVICE_WIN32_OWN_PROCESS,
                 SERVICE_DEMAND_START, 
                 SERVICE_ERROR_NORMAL,
                 szFilePath, 
                 NULL, 
                 NULL, 
                 _T(
"RPCSS
函数的原型如下:
SC_HANDLE CreateService(
    SC_HANDLE hSCManager,       
// handle to SCM database 
    LPCTSTR lpServiceName,      // name of service to start
    LPCTSTR lpDisplayName,      // display name
    DWORD dwDesiredAccess,      // type of access to service
    DWORD dwServiceType,        // type of service
    DWORD dwStartType,          // when to start service
    DWORD dwErrorControl,       // severity of service failure
    LPCTSTR lpBinaryPathName,   // name of binary file
    LPCTSTR lpLoadOrderGroup,   // name of load ordering group
    LPDWORD lpdwTagId,          // tag identifier
    LPCTSTR lpDependencies,     // array of dependency names
    LPCTSTR lpServiceStartName, // account name 
    LPCTSTR lpPassword          // account password
);
具体的细节可以查一下MSDN,我只说一下第六个和第十一个参数。第六个参数是服务的启动类型。
SERVICE_DEMAND_START是手动启动,SERVICE_AUTO_START是自动启动。第十一个参数是服务的依存关系,比如说服务的启动想要依存SQL Server的启动,那我们可以把这个参数写成:
_T("MSSQLSERVER/0");

如果我们写的服务不依存于其他的任何服务,那我们就将此参数设置为NULL就可以了。

  接下来,我们为上面的"什么也不做"的服务添加一个简单的功能:做数字的累加,并且把结果写到系统的"应用程序日志"中去。
  首先,我们在类CServiceModule中添加一个成员变量:int n; 在Init()中对n进行初始化:
n = 0;
然后在类CServiceModule中添加一个成员函数Adder():

void CServiceModule::Adder()
{
    n 
++;
    CString str;
    str.Format(
"%i",n);
    LogEvent(str);
}

编译…出错了。??,提示 CString 没有定义,难道在ATL中无法用 MFC 吗?让我们看看设置:菜单Project->Setting ,General面板,默认的设置是:Use MFC in a Static Library。那为什么不可以用MFC中的类呢?原来是头文件没有包含,这个不知道算不算 VC 的一个 Bug : ,设置中默认是用MFC,可是却没有包含相应的头文件。那我们就自己加上好了。在StdAfx.h中加上:#include ,注意要加到#include 的前面,要不然又要编译出错了。接下来,我们在程序中再添加一个Timer,让这个Timer每两秒钟调用一次Adder,做一次累加。在
MSG msg;
while (GetMessage(&msg, 000))
    DispatchMessage(
&msg);
的前面加上代码:
SetTimer(NULL,1,2000,(TIMERPROC)OnTimerProc); 
注意一定要加在前面,因为要是加到while循环的下面,就没有机会执行了。再添加一个全局的回调函数OnTimerProc 如下:
VOID CALLBACK OnTimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
    _Module.Adder();
}
好了,大功告成。编译,然后在SCM中启动我们的服务。在控制面板中打开"事件查看器",看一下运行的结果,如下图四:


图四

好了,就写到这里吧,其他的内容大家自己深究吧。祝各位编程愉快!

相关文章推荐

用 VC 2008 编写 Windows Service(系统服务) atl 编写系统服务

http://hi.baidu.com/lewutian/item/9019396a05d517166995e6a5 http://hi.baidu.com/cntrump/item/2bf6b43...

VS2005 ATL WINDOWS服务感想

最近写的WINDOWS 服务,以前用VC6写过简单的服务。VC6 带的ATL 创建服务后,会生成一个继承于CcomModule 的类,并覆盖了START、STOP等(不记得了),只需在START、ST...

Windows ATL Service 服务的创建(VS2010)

1 使用VS2010床加一个ATL服务项目 第一步 第二步 第三步 创建好之后, 重写父类的以下方法 HRESULT RegisterAppId(bool ...

vs2010 ATL创建windows服务程序

1,new project -> 选择 ATL Project,  设置工程名,如:PureSsl 2,在向导的“Application Setting”页,“Application Type”项选...

VS2010 ATL服务程序编写全攻略(二) - 内核对象访问

在上一篇中,我们实现了基本的ATL系统服务框架,在这一篇中,我们来看一看服务程序与应用程序内核对象的访问。 首先,先在ATL服务中创建一个内核对象,这里我选用了事件对象。 在上...

VS2010 ATL服务程序编写全攻略(三) - 创建用户桌面进程(突破Session 0隔离)

上一篇中,我们完成了服务层与应用层的内核对象访问。 这篇文件,将主要说明如何在服务层创建一个用户进程,显示在用户桌面上,并且允许交互。 这里就引入了Windows Vista之后的Session ...

C++ATL服务类

  • 2013年10月01日 09:03
  • 3KB
  • 下载

VS2008 ATL写系统服务

下面就是用 Visual Studio 2008 中的 VC++ 2008 写系统服务的详细步骤(我用的 VC 是英文版的): 1. 新建项目。 1-1. 启动 Visual Studio 200...

ATL服务程序启动界面问题

开发中有时会遇到这样的问题,当服务程序需要使用某些功能时,由于用户的关系而受到限制,比如访问注册表的HKEY_CURRENT_USER键,使用网络等等,这时候就需要以当前登陆用户的身份去进行操作,通常...

[ATL/WTL]_[初级]_[Windows消息循环初解]

Windows 消息循环初解场景 Win32窗口编程, 肯定涉及到消息循环. Win32编程基本就是通过处理消息来处理系统任务, 所以Win32窗口编程, 弄懂消息循环是必然的. 说明1.对于GUI线...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用 ATL 编写 Windows 服务
举报原因:
原因补充:

(最多只允许输入30个字)