不登记dll调用atl实现的com对象

不注册dll调用atl实现的com对象

最近做一个通用的com组件调用框架,用一个注册好的factory.dll去创建另一个com.dll里面的接口,返回这个接口给脚本语言用;

结果发现如果是delphi写的dll,没有问题,如果是atl实现的dll,则会报TYPE_E_LIBNOTREGISTERED错误,让我十分郁闷,今天下决心解决,于是跟踪看了下atlcom.h里的代码,发现是GetTI这函数在作怪,代码如下所示

ITypeLib* pTypeLib = NULL;
		if (InlineIsEqualGUID(CAtlModule::m_libid, *m_plibid) && m_wMajor == 0xFFFF && m_wMinor == 0xFFFF)
		{
			TCHAR szFilePath[MAX_PATH];
			DWORD dwFLen = ::GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szFilePath, MAX_PATH);
			if( dwFLen != 0 && dwFLen != MAX_PATH )
			{
				USES_CONVERSION_EX;
				LPOLESTR pszFile = T2OLE_EX(szFilePath, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
#ifndef _UNICODE
				if (pszFile == NULL)
					return E_OUTOFMEMORY;
#endif
				hRes = LoadTypeLib(pszFile, &pTypeLib);
			}
		}
		else
		{
			ATLASSUME(!InlineIsEqualGUID(*m_plibid, GUID_NULL) && "Module LIBID not initialized. See DECLARE_LIBID documentation.");
			hRes = LoadRegTypeLib(*m_plibid, m_wMajor, m_wMinor, lcid, &pTypeLib);
}

仔细阅读后发现,如果m_libid于传进来的m_plibid相等,并且m_wMajor == 0xFFFF && m_wMinor == 0xFFFF这个条件符合,就会加载当前模块的typelib,否则就会到注册表里去加载;而m_wMajo和m_wMinor这两个值 是从IDispatchImpl这里传进来的,于是将继承类改为

public IDispatchImpl<IParam, &IID_ITestIntf, &LIBID_TestLib, /*wMajor =*/ 0xFFFF, /*wMinor =*/ 0xFFFF>
再编译,用c#的dynamic 测试了一下,完美运行。