前段时间有个开发一个Windows服务的需求,且不能使用.NET, 之后在对比了Win32 和 ATL两种编写Windows服务的途径, 还是选择了后者.
Mark几个地方
重载InitializeSecurity()函数
1
2
3
4
5
6
7
8
9
10HRESULT InitializeSecurity() throw()
{
// TODO : 调用 CoInitializeSecurity 并为服务提供适当的
// 安全设置
// 建议 - PKT 级别的身份验证、
// RPC_C_IMP_LEVEL_IDENTIFY 的模拟级别
// 以及适当的非 NULL 安全说明符。
return CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE,
RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL );
}重载RegisterAppId函数,注册服务的相关信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36HRESULT CXXXXXServiceModule::RegisterAppId(bool bService = false) throw()
{
HRESULT hr = S_OK;
BOOL res = __super::RegisterAppId(bService);
if (bService)
{
if (IsInstalled())
{
SC_HANDLE hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SC_HANDLE hService = NULL;
if (hSCM == NULL)
hr = AtlHresultFromLastError();
else
{
hService = ::OpenService(hSCM, m_szServiceName, SERVICE_ALL_ACCESS);
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("这里添加服务的描述内容"));
Description.lpDescription = szDescription;
::ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &Description);
::CloseServiceHandle(hService);
}
else
hr = AtlHresultFromLastError();
::CloseServiceHandle(hSCM);
}
}
}
return hr;
}重载
run( )
函数, 网上有的说重载PreMessageLoop( )
函数添加自定义代码,其实看atl头文件, 重载run比较”正宗”.1
2
3
4
5HRESULT CXXXXXServiceModule::Run(int nShowCmd) throw()
{
// 添加服务启动的自定义代码
return __super::Run(nShowCmd);
}重载stop( )函数, 添加服务停止的相关代码.
1
2
3
4
5void CXXXXXServiceModule::OnStop() throw()
{
// 释放所有资源
__super::OnStop();
}
以上这些函数都不能抛出异常,这点很重要, 最好都用try{ } catch(){}
块捕获, 如果有异常的话服务的操作就会失败造成服务的无响应.同时为了不让服务的启动和停止超时, 最好开启别的线程去完成任务.
注册服务: MyService.exe /Service
卸载服务: MyService.exe /UnRegServer
调试/测试服务的时候难免会导致服务进程的崩溃, 服务列表上无法操作, 这时候检查下面几点去清除/卸载服务:
- 如果有安装程序, 在添加/删除程序里卸载服务的程序, 前提条件是服务有响应, 并且卸载服务的命令不能有异常和失败;
- 在注册表路径
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services]
中找到自己的服务,删除; - 在注册表里搜索自己的服务名, 删除所有的键值;
- 任务管理器里结束服务进程.