一、基本过程
1、创建
Visual Studio 2008 -> 新建项目 -> ATL -> 服务(EXE)
2、注册
(1)、服务的注册:命令行输入 MyService.EXE /Service (或MyService /Service)
(2)、服务的删除:SC DELETE MyService (服务名,非文件名)
(本地服务器注册:MyService /RegServer 或 MyService -RegServer;
注销:MyService /UnRegServer 或 MyService -UnRegServer
)
注:方便起见,一般用文件名进行注册和删除:
MyService /Service
MyService /UnRegServer
3、在stdafx.h中添加:#define _ATL_NO_COM_SUPPORT
因为PreMessageLoop()没有返回S_OK,而是尝试注册COM对象,如果Windows Service不包含COM组件,则需加上此句
4、重载CAtlServiceModuleT::Run()函数:
HRESULT CMyServiceModule::Run(int nShowCmd = SW_HIDE) throw()
{
OutputDebugString(L"\nRun"); //输出信息到调试窗口
LogEvent(L"\nRun"); //输出信息到事件查看器
SetTimer(NULL,1,2000,(TIMERPROC)OnTimerProc); //设置定时器
DWORD dwID;
HANDLE hThread;
hThread = ::CreateThread(0, 0, MyThreadWrapper, (void*)this,0,&dwID); //开启新线程
return __super::Run();
}
//定时器函数
VOID CALLBACK OnTimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
_AtlModule.MyProc();
}
void CMyServiceModule::MyProc()
{
static int n=0;
n++;
CString str;
str.Format(L"%i",n);
LogEvent(str);
}
5、重载CAtlServiceModuleT::OnStop()函数:
//停止服务
void CMyServiceModule::OnStop() throw()
{
OutputDebugString(L"\nOnStop");
LogEvent(L"OnStop");
__super::OnStop();
}
6、最好在Run中启动多线程,参见线程管理器类
二、修改服务的配置
{
HRESULT hr = S_OK;
BOOL res = __super::RegisterAppId(bService);
if (bService)
{
if (IsInstalled())
{
SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SERVICE_CHANGE_CONFIG);
SC_HANDLE hService = NULL;
if (hSCM == NULL)
hr = AtlHresultFromLastError();
else
{
hService = ::OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG);
if (hService != NULL)
{
::ChangeServiceConfig(hService, SERVICE_NO_CHANGE,
SERVICE_AUTO_START, // 修改服务为自动启动
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
m_szServiceName); // 通过修改资源IDS_SERVICENAME 修改服务的显示名字
SERVICE_DESCRIPTION Description;
TCHAR szDescription[ 1024 ];
ZeroMemory(szDescription, 1024 );
ZeroMemory( & Description, sizeof (SERVICE_DESCRIPTION));
lstrcpy(szDescription, _T( " Windows服务示例,by zhouping2000@gmail.com " )); // 修改服务说明
Description.lpDescription = szDescription;
::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, & Description);
::CloseServiceHandle(hService);
}
else
hr = AtlHresultFromLastError();
::CloseServiceHandle(hSCM);
}
}
}
return hr;
}
三、定时器
{
_AtlModule.Adder();
}
extern " C " int WINAPI _tWinMain(HINSTANCE /* hInstance */ , HINSTANCE /* hPrevInstance */ ,
LPTSTR /* lpCmdLine */ , int nShowCmd)
{
// 只是为演示;应该在重载Run()函数
SetTimer(NULL, 1 , 2000 ,(TIMERPROC)OnTimerProc);
MSG msg;
while (GetMessage( & msg, 0 , 0 , 0 ))
DispatchMessage( & msg);
return _AtlModule.WinMain(nShowCmd);
}
void CMyServiceModule::Adder()
{
n ++ ;
CString str;
str.Format(L " %i " ,n);
LogEvent(str); // 写入事件查看器
}
四、重载Windows Service运行函数Run()
{
SetTimer(NULL, 1 , 2000 ,(TIMERPROC)OnTimerProc); // 应该在GetMessage()循环之上
MSG msg;
while (GetMessage( & msg, 0 , 0 , 0 ))
DispatchMessage( & msg);
return S_OK;
}