我正在开发一个包含多个 C++ COM Dll 的遗留项目。每次在调试配置上构建解决方案时,构建过程都会为每个 COM 项目提供错误:
Error 10 error MSB3073: The command "
regsvr32 /s /c "D:\*****removed intentionally****_d.dll"
echo regsvr32 exec. time > ".\Debug\regsvr32.trg"
echo Server registration done!
:VCEnd
" exited with code -1073741819.
我最近加入了这个项目,所以当我询问它时,我被告知每个人都忽略这些错误,因为解决方案在第二次构建时成功构建。
我决定深入挖掘,似乎 COM 注册本身成功(这解释了为什么第二次构建没有重新尝试注册),但是对 regsvr32 的调用返回错误代码(0xC0000005)。这就是构建失败的原因。
我还尝试从自定义构建步骤中删除注册,而是选择从链接器属性表“Register Output=YES”中注册,并得到相同的错误。
我尝试使用其中一个 dll 调试 regsvr32 并发现以下内容:
起初我无法在 DllRegisterServer 中设置断点,然后我尝试调试 regsvr32 的 X86 版本(来自 Windows\SysWOW64),然后才能在 DllRegisterServer 上中断。有人可以解释一下吗?
DllRegisterServer 成功并返回 S_OK。
DllRegisterServer 返回后,抛出异常,异常和堆栈跟踪如下:
regsvr32.exe 中 0x759849c1 处的第一次机会异常:0xC0000005:访问冲突读取位置 0x005bf028。
oleaut32.dll!_MemFree@4() + 0x25 bytes
oleaut32.dll!OLE_TYPEMGR::Release() + 0x1b138 bytes
oleaut32.dll!ReleaseAppData() + 0x317 bytes
oleaut32.dll!_OACleanup@0() + 0x5 bytes
ole32.dll!wCoUninitialize(COleTls & Tls, int fHostThread) Line 2830 C++
ole32.dll!CoUninitialize() Line 2620 C++
regsvr32.exe!_wWinMain@16() + 0xa77 bytes
regsvr32.exe!__initterm_e() + 0x1b1 bytes
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
那么您对此有何看法?我是否应该像团队其他成员一样忽略它(产品在开发和生产中运行良好)?
您知道为什么即使注册成功我也会遇到访问冲突吗?注册 COM dll 后是否还有其他进程/逻辑运行?还有其他方向吗?
这是处理注册的类的代码:
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_C3DT2D, CC3DT2D)
END_OBJECT_MAP()
class CMy3DT2DApp : public CWinApp
{
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMy3DT2DApp)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
//{{AFX_MSG(CMy3DT2DApp)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CMy3DT2DApp, CWinApp)
//{{AFX_MSG_MAP(CMy3DT2DApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CMy3DT2DApp theApp;
BOOL CMy3DT2DApp::InitInstance()
{
_Module.Init(ObjectMap, m_hInstance, &LIBID_MY3DT2DLib);
return CWinApp::InitInstance();
}
int CMy3DT2DApp::ExitInstance()
{
_Module.Term();
return CWinApp::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return (AfxDllCanUnloadNow()==S_OK && _Module.GetLockCount()==0) ? S_OK : S_FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
return _Module.GetClassObject(rclsid, riid, ppv);
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
return _Module.UnregisterServer(TRUE);
}