前几天面试,被问到这个问题,当时我说“没用vc做过,可能在.Net下面做比较简单吧,因为记得库里面好像封装了一下了”因为我记得以前的一个网站测试的一个项目好像也有这么一个工具的。
今天又看到有人在百度知道问这个问题,于是就看了一下。在网上搜索一下,资料还是比较多的。
回来用vc2008试了一下,如下:
新建一个 ATL 项目-》 选择创建一个“服务”类型的ATL 项目,将生成如下代码,
// widebright_service.cpp : WinMain 的实现
#include "stdafx.h"
#include "resource.h"
#include "widebright_service_i.h"
#include <stdio.h>
class Cwidebright_serviceModule : public CAtlServiceModuleT< Cwidebright_serviceModule, IDS_SERVICENAME >
{
public :
DECLARE_LIBID(LIBID_widebright_serviceLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_WIDEBRIGHT_SERVICE, "{4B7ADCD4-B9BF-43F2-BAD3-F858A926FAD5}")
HRESULT InitializeSecurity() throw()
{
// TODO : 调用 CoInitializeSecurity 并为服务提供适当的
// 安全设置
// 建议 - PKT 级别的身份验证、
// RPC_C_IMP_LEVEL_IDENTIFY 的模拟级别
// 以及适当的非 NULL 安全说明符。
return S_OK;
}
//重写这个函数来启动任务啦
HRESULT Run(int nShowCmd = SW_HIDE) throw()
{
HRESULT hr = S_OK;
hr = __super::PreMessageLoop(nShowCmd);
if (hr == S_OK)
{
if (m_bService)
{
//可以在这里启动线程,或者什么其他东西来做自己的工作的啦
//这里是什么都没有做了,只输出一条信息
LogEvent(_T("widebright 的服务启动咯,呵呵 "));
SetServiceStatus(SERVICE_RUNNING);
}
//进入消息循环,不停的处理消息,可能最后分发到Handler去处理,调用了OnShutdown等函数的。
__super::RunMessageLoop();
}
if (SUCCEEDED(hr))
{
hr = __super::PostMessageLoop();
}
//可以在适当的时候调用Uninstall函数来卸载掉服务
//__super::Uninstall();
return hr;
}
//重写,服务退出处理
void OnShutdown() throw()
{
LogEvent(_T("widebright 的服务退出咯,一点都不好玩呵呵 "));
}
};
Cwidebright_serviceModule _AtlModule;
//
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/, int nShowCmd)
{
return _AtlModule.WinMain(nShowCmd);
}
紫色部分代码是自己添加上去,可以看到 CAtlServiceModuleT (http://msdn.microsoft.com/en-us/library/hkhzk29d(VS.80).aspx) 类已经把所有的东西封装的比较完整了。
我只要根据需要重写相应的函数来实现自己想要的功能就行了,比如你想创建的“服务”随系统启动,可以重写CAtlServiceModuleT 的Install函数,把里面的CreateService函数的参数修改一下,具体可以去MSDN上查找CreateService这个API的说明。
如果想处理服务 停止和启动的动作,可以参考CAtlServiceModuleT 的源代码重写OnStop ()等函数。我上面简单到重写了Run函数,输出一条“事件”其实具体 工作是可以放到这里来完成的吧。
编译,生成程序之后就可以测试了,
执行“widebright_service -/Service” 就可以把服务注册到系统了,命令行参数其实是在CAtlServiceModuleT::ParseCommandLine 这个函数里面处理,可以去看一下,必要的话重写也是可以的,加上调用 UnInstall来删除服务的代码也很不错的吧。
注册后,就看用“sc start” 或者“net start” 等命令来操纵服务了。在“服务”控制器里面控制与可以:如图
在 “事件查看器”中可以看到自己的服务生成 到事件。
注意:
我测试时需要添加_ATL_NO_COM_SUPPORT这个宏的标志,才能正确运行到Run函数里面,好像是com初始化的时候失败了如果没有定义这个的话。
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
#pragma once
#ifndef STRICT
#define STRICT
#endif
#include "targetver.h"
#define _ATL_NO_COM_SUPPORT
#define _ATL_APARTMENT_THREADED
#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的
#include "resource.h"
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
using namespace ATL;
参考:
关于Windows服务的详细信息看到MSDN上搜索“windows service",可以找到原理,和控制接口等相关编程用法。
VC知识库文章- 用C 语言编写Windows 服务程序的五个步骤
http://www.vckbase.com/document/viewdoc/?id=1474
http://www.vckbase.com/document/listdoc.asp?sclsid=1319
等都是不错的参考资料