用ATL编写Windows服务

0 篇文章 0 订阅

有时候,我们需要自己写的程序在没有用户登陆的情况下,只要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\0"),
         NULL,
         NULL);

函数的原型如下:

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, 0, 0, 0))
  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中启动我们的服务。在控制面板中打开"事件查看器",看一下运行的结果,如下图四:

图四

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

本文配套源码


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想在 Windows 平台上开发 C++ 应用程序,并且需要使用 ATL(Active Template Library)技术来简化 COM 组件开发,可以按照以下步骤操作: 1. 安装 Visual Studio:ATL 是 Visual C++ 的一个组件,因此需要安装 Visual Studio(包括 Visual C++ 组件)才能使用 ATL。你可以从 Microsoft 官网下载最新版本的 Visual Studio,也可以使用早期版本的 Visual Studio。 2. 创建 ATL 项目:在 Visual Studio 中,选择“File”->“New”->“Project”->“ATL”->“ATL Project”,然后按照向导创建一个 ATL 项目。 3. 编写 COM 组件代码:在 ATL 项目中,你可以使用 ATL 宏和模板来快速开发 COM 组件。具体来说,你可以使用 `ATL::CComObjectRootEx` 类来定义 COM 对象的基本行为,使用 `ATL::CComCoClass` 宏来定义 COM 对象的类工厂,使用 `ATL::CComPtr` 类来管理 COM 对象之间的引用计数等。 4. 注册 COM 组件:在 ATL 项目中,你可以使用 `ATL::CComModule` 类来管理 COM 组件的注册表信息。具体来说,你需要在 `DllMain` 函数中调用 `ATL::CComModule::Init` 函数来初始化 COM 模块,然后在 `DllMain` 函数中调用 `ATL::CComModule::Term` 函数来清理 COM 模块。如果你想手动注册 COM 组件,可以使用 `ATL::AtlRegisterClassCategoriesHelper` 函数和 `ATL::AtlRegisterClassObject` 函数来实现。 5. 使用 COM 组件:在其他应用程序中,你可以使用 COM 组件的类 ID 和接口 ID 来创建 COM 对象,并调用 COM 对象的方法来实现特定功能。具体来说,你可以使用 `CoCreateInstance` 函数来创建 COM 对象,使用 `QueryInterface` 函数来获取 COM 对象的接口指针,然后使用接口指针来调用 COM 对象的方法。 总之,使用 ATL 技术可以帮助你更快速、更方便地开发高质量的 COM 组件,并在 Windows 平台上实现各种应用程序之间的互操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值