覆盖PreMessageLoop,何时应该调用CAtlServiceModuleT :: PreMessageLoop

时间:2011-10-24 20:19:47

标签: visual-studio-2010 visual-c++ visual-studio-2005 atl

我在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状态。那是明智的吗?

2 个答案:

答案 0 :(得分:1)

首先,“if(ERROR_SUCCESS == result)”是不完全正确的,因为你应该根据HRESULT值检查结果,这是针对S_OKS_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;
}