我在Visual Studio 2005中有一个已转换为Visual Studio 2010项目的服务项目。我注意到PreMessageLoop函数存在问题,如下所示:
HRESULT CMyModule::PreMessageLoop (int nShowCmd)
{
HRESULT result = CAtlServiceModuleT<CMyModule,100>::PreMessageLoop(nShowCmd);
if (ERROR_SUCCESS == result)
{
ComplicatedInitialization();
_AtlModule.SetServiceStatus (SERVICE_START_PENDING);
MoreComplicatedInitialization();
_AtlModule.SetServiceStatus (SERVICE_START_PENDING);
StillMoreComplicatedInitialization();
_AtlModule.SetServiceStatus (SERVICE_START_PENDING);
EvenMoreComplicatedInitialization();
}
return result;
}
这在Visual C ++ 2005中运行良好:Run函数调用我的PreMessageLoop,它调用基类PreMessageLoop。当服务处于SERVICE_START_PENDING时,会发生复杂的初始化。当我的PreMessageLoop返回时,Run调用SetServiceStatus(SERVICE_RUNNING)。
Visual C ++ 2010与众不同:基类PreMessageLoop调用SetServiceStatus(SERVICE_RUNNING)。当服务处于SERVICE_RUNNING状态时会发生复杂的初始化,这是不好的(因为当服务实际上仍在初始化时,服务看起来正在运行)。
我可以简单地将基类PreMessageLoop调用移到我的PreMessageLoop调用的底部吗?或者它比简单的举动更复杂?
服务似乎可以从SERVICE_RUNNING状态返回到SERVICE_START_PENDING状态。那是明智的吗?
答案 0 :(得分:1)
首先,“if(ERROR_SUCCESS == result)”是不完全正确的,因为你应该根据HRESULT值检查结果,这是针对S_OK
,S_FALSE
或使用{ {1}}种宏。
Base SUCCEEDED
正在注册COM类对象,如果你的复杂初始化没有使用COM实例,你可以自由地将你的东西移到PreMessageLoop
调用之上。
答案 1 :(得分:0)
PreMessageLoop中的COM初始化代码导致错误1053。
解决方案1:禁用COM支持。
#define _ATL_NO_COM_SUPPORT
在所有ATL相关的包括之前,在“stdafx.h”中。
解决方案2:覆盖“PreMessageLoop”并从COM初始化代码中删除它。
HRESULT PreMessageLoop(_In_ int nShowCmd) throw()
{
if (m_bService)
{
// Make sure that service was not stoped during initialization
if (::InterlockedCompareExchange(&m_status.dwCurrentState, SERVICE_RUNNING, SERVICE_START_PENDING) == SERVICE_START_PENDING)
{
LogEvent(_T("Service started/resumed"));
::SetServiceStatus(m_hServiceStatus, &m_status);
}
}
// Start the tread(s)
_worker = new CWorkerThread();
return S_OK;
}