其他:
无COM接口的ATL服务程序启动失败的解决办法: http://hi.baidu.com/hstrong/item/11dc5c98e4d58fdf1b49dfab
windows服务ATL模板 服务启动后再停止出错,并且无法删除:http://fireflyliu.is-programmer.com/posts/15575.html
http://zhanyonhu.blog.163.com/blog/static/161860442010101751258317/
VC 2010+ATL:ATL服务程序无法启动
By:zhanyonhu
VC 2010+ATL:ATL服务程序无法启动,长时间等待后,显示启动失败,服务没有响应。而事实上服务进程已经启动成功!原因是没有设置服务状态为“正在运行”。加上:SetServiceStatus(SERVICE_RUNNING); 就可以了。
此前的VC版本似乎没有这个问题吧?
完整的代码框架:
// ServerService.cpp : WinMain 的实现
#include "stdafx.h"
#include "resource.h"
#include "ServerService_i.h"
#include <time.h>
#include <stdio.h>
class CServerServiceModule : public CAtlServiceModuleT< CServerServiceModule, IDS_SERVICENAME >
{
public :
DECLARE_LIBID(LIBID_ServerServiceLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SERVERSERVICE, "{40838A6D-2976-416A-A1C1-CF88F76BEB0B}")
HRESULT InitializeSecurity() throw()
{
// TODO : 调用 CoInitializeSecurity 并为服务提供适当的
// 安全设置
// 建议 - PKT 级别的身份验证、
// RPC_C_IMP_LEVEL_IDENTIFY 的模拟级别
// 以及适当的非 NULL 安全说明符。
HRESULT hr=S_OK;
hr = CoInitializeSecurity(NULL, -1, NULL, NULL,RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_NONE, NULL);
ATLASSERT(SUCCEEDED(hr));
return S_OK;
}
public :
CServerServiceModule::CServerServiceModule() throw()
{
HRESULT hr=S_OK;
hr = CoInitialize(NULL);
ATLASSERT(SUCCEEDED(hr));
}
CServerServiceModule::~CServerServiceModule() throw()
{
CoUninitialize();
}
inline HRESULT RegisterAppId(_In_ bool bService = false) throw()
{
if (!Uninstall())
return E_FAIL;
HRESULT hr = CServerServiceModule::UpdateRegistryAppId(TRUE);
if (FAILED(hr))
return hr;
CRegKey keyAppID;
LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);
if (lRes != ERROR_SUCCESS)
return AtlHresultFromWin32(lRes);
CRegKey key;
lRes = key.Create(keyAppID, CServerServiceModule::GetAppIdT());
if (lRes != ERROR_SUCCESS)
return AtlHresultFromWin32(lRes);
key.DeleteValue(_T("LocalService"));
if (!bService)
return S_OK;
key.SetStringValue(_T("LocalService"), m_szServiceName);
// Create service
if (!Install())
return E_FAIL;
return S_OK;
}
BOOL Install() throw()
{
if (IsInstalled())
return TRUE;
// Get the executable file path
TCHAR szFilePath[MAX_PATH + _ATL_QUOTES_SPACE];
DWORD dwFLen = ::GetModuleFileName(NULL, szFilePath + 1, MAX_PATH);
if( dwFLen == 0 || dwFLen == MAX_PATH )
return FALSE;
// Quote the FilePath before calling CreateService
szFilePath[0] = _T('\"');
szFilePath[dwFLen + 1] = _T('\"');
szFilePath[dwFLen + 2] = 0;
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
TCHAR szBuf[1024];
if (AtlLoadString(ATL_SERVICE_MANAGER_OPEN_ERROR, szBuf, 1024) == 0)
#ifdef UNICODE
Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager"));
#else
Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager"));
#endif
MessageBox(NULL, szBuf, m_szServiceName, MB_OK);
return FALSE;
}
SC_HANDLE hService = ::CreateService(
hSCM, m_szServiceName, m_szServiceName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL);
if (hService == NULL)
{
::CloseServiceHandle(hSCM);
TCHAR szBuf[1024];
if (AtlLoadString(ATL_SERVICE_START_ERROR, szBuf, 1024) == 0)
#ifdef UNICODE
Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not start service"));
#else
Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not start service"));
#endif
MessageBox(NULL, szBuf, m_szServiceName, MB_OK);
return FALSE;
}
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
return TRUE;
}
void CServerServiceModule::OnStop() throw()
{
__super::OnStop();
}
void CServerServiceModule::Handler(DWORD dwOpcode)
{
// TODO: 在此添加专用代码和/或调用基类
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
break;
case SERVICE_CONTROL_PAUSE:
break;
case SERVICE_CONTROL_CONTINUE:
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
break;
default:
//LogEvent将日志记录到windows的系统日志中
//LogEvent(_T("Bad service request"));
break;
}
__super::Handler(dwOpcode);
}
HRESULT CServerServiceModule::PreMessageLoop(int nShowCmd)
{
HRESULT hr = CAtlServiceModuleT<CServerServiceModule, IDS_SERVICENAME>::PreMessageLoop(nShowCmd);
if (m_bService)
{
//设定服务状态——已经启动,正在运行
SetServiceStatus(SERVICE_RUNNING);
hr = S_OK;
}
return hr;
}
};
CServerServiceModule _AtlModule;
//
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
LPTSTR lpCmdLine, int nShowCmd)
{
return _AtlModule.WinMain(nShowCmd);
}