最近一直写SSLVPN客户端,和10年前的项目类似,都是com调用com。
创建ATL Service,在PreMessageLoop函数中调用其他的com组件,出现CoInitialize not called (800401f0)。我记得类似的代码在vs2005中运行正常,经过两天的代码对比后,
class ATL_NO_VTABLE CAtlServiceModuleT :
public CAtlExeModuleT
以前,com的初始化在CAtlExeModuleT的构造函数中作,
InitializeCom()函数从CAtlExeModuleT的构造函数,移到了CAtlExeModuleT::winmain(),但是 CAtlServiceModuleT::winmain,并没有调用InitializeCom()。
微软的专家给出了解决方案
在atlbase.h文件文件中CAtlServiceModuleT::Start中将
HRESULT Start(_In_ int nShowCmd) throw()
{
T* pT = static_cast(this);
// Are we Service or Local Server
CRegKey keyAppID;
LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ);
if (lRes != ERROR_SUCCESS)
{
m_status.dwWin32ExitCode = lRes;
return m_status.dwWin32ExitCode;
}
CRegKey key;
lRes = key.Open(keyAppID, pT->GetAppIdT(), KEY_READ);
if (lRes != ERROR_SUCCESS)
{
m_status.dwWin32ExitCode = lRes;
return m_status.dwWin32ExitCode;
}
TCHAR szValue[MAX_PATH];
DWORD dwLen = MAX_PATH;
lRes = key.QueryStringValue(_T("LocalService"), szValue, &dwLen);
m_bService = FALSE;
if (lRes == ERROR_SUCCESS)
m_bService = TRUE;
if (m_bService)
{
SERVICE_TABLE_ENTRY st[] =
{
{ m_szServiceName, _ServiceMain },
{ NULL, NULL }
};
if (::StartServiceCtrlDispatcher(st) == 0)
m_status.dwWin32ExitCode = GetLastError();
return m_status.dwWin32ExitCode;
}
// local server - call Run() directly, rather than
// from ServiceMain()
m_status.dwWin32ExitCode = pT->Run(nShowCmd);
return m_status.dwWin32ExitCode;
}
改为
if (::StartServiceCtrlDispatcher(st) == 0)
m_status.dwWin32ExitCode = GetLastError();
return m_status.dwWin32ExitCode;
}
// local server - call Run() directly, rather than
// from ServiceMain()
#pragma region Run wrapped by InitializeCom/UninitializeCom
// FIX: See
#ifndef _ATL_NO_COM_SUPPORT
HRESULT hr = E_FAIL;
hr = T::InitializeCom();
if (FAILED(hr))
{
// Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing
// COM and InitializeCOM trying to initialize COM with different flags.
if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL)
return hr;
} else
m_bComInitialized = true;
m_status.dwWin32ExitCode = pT->Run(nShowCmd);
if (m_bComInitialized)
T::UninitializeCom();
#else
m_status.dwWin32ExitCode = pT->Run(nShowCmd);
#endif
#pragma endregion
return m_status.dwWin32ExitCode;
}
我一般不大愿意修改atl的代码,还是在
_tWinMain()函数中添加
_AtlModule.InitializeCom();
经过确认,没有这行代码,release版本在退出时,也会有错误发生
阅读(4397) | 评论(0) | 转发(0) |