分享

COM调用过程

 king9413 2013-06-25

Yes, it basically makes no sense to me that VB6 doesn't look up the registry keys.  It just doesn't.  COM object creation is usually done like this (simplified):

  1. From the "friendly name" of the coclass (COM object), obtain the CLSID from the registry.  Example:  Scripting.Dictionary is the friendly name and it maps to CLSID {EE09B103-97E0-11CF-978F-00A02463E06F} (see HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Scripting.Dictionary\CLSID).
  2. Using that CLSID, CoCreateInstance() is called.  Internally this does the lookup of the COM server binary in HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID.  In our example, HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{EE09B103-97E0-11CF-978F-00A02463E06F}\InprocServer32 with a value of C:\Windows\system32\scrrun.dll.
  3. LoadLibrary() is used to load the dll and then the entry point for DllGetClassObject() is obtained.
  4. DllGetClassObject() is called using the CLSID desired.  This returns an IClassFactory pointer that is ultimately used to create the desired object.

All this should be happening in both .Net and VB6.  I see no other way around it.  In your case, the IClassFactory is returning 0x80040111 if the loaded DLL doesn't supply the COM object that corresponds to the given CLSID; and you get 0x80040111 probably from step 2 from the call to CoCreateInstance() when it doesn't find the desired CLSID under HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID.


-------------

1. I guess the next thing to do would be the tough job of debugging the class factory code.

 

2. To do this, you need to start debugging your COM DLL and set the C# client app as the startup application.

2.1 Via project properties, set the debugger type to "Mixed" so that you can see the C# client code.

2.2 Then place a breakpoint in your global DllGetClassObject() function. This function was generated by the ATL wizard for your DLL. It should look something like the following :

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
    return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
}

2.3 Start debugging. Note well that if you are able to reach the DllGetClassObject() function, it is clear that your COM DLL has been registered correctly. If you are not able to even reach DllGetClassObject(), something has gone wrong and we may be back to registration problems again.

2.4 If you do reach DllGetClassObject(), step through all the way until you reach the AtlComModuleGetClassObject() function (this is the ATL source code from my machine which uses VS2008) :

ATLINLINE ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
 if (ppv == NULL)
  return E_POINTER;
 *ppv = NULL;

 ATLASSERT(pComModule != NULL);
 if (pComModule == NULL)
  return E_INVALIDARG;
 if (pComModule->cbSize == 0)  // Module hasn't been initialized
  return E_UNEXPECTED;

 HRESULT hr = S_OK;

 for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++)
 {
  if (*ppEntry != NULL)
  {
   _ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
   if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid))
   {
    if (pEntry->pCF == NULL)
    {
     CComCritSecLock<CComCriticalSection> lock(pComModule->m_csObjMap, false);
     hr = lock.Lock();
     if (FAILED(hr))
     {
      ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in AtlComModuleGetClassObject\n"));
      ATLASSERT(0);
      break;
     }
     if (pEntry->pCF == NULL)
      hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF);
    }
    if (pEntry->pCF != NULL)
     hr = pEntry->pCF->QueryInterface(riid, ppv);
    break;
   }
  }
 }

 if (*ppv == NULL && hr == S_OK)
  hr = CLASS_E_CLASSNOTAVAILABLE;
 return hr;
}

Note the highlighted error code CLASS_E_CLASSNOTAVAILABLE. This error code has value 0x80040111. Step through and see in what situation will this error code be returned.

2.5 Best of luck, Jicky.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多