COM Interop - Member not found

2

I'm try to write a plugin for a 3rd party product. This takes the form of a native C++ DLL, which implements a specified interface from a supplied type library. My plugin is getting loaded successfully, and the methods described by the interface are being called at the expected points, I can write out a log file from my plugin and query a web service, so far so good.

However, for my plugin to query the main program, the Initialize() method passes an IDispatch interface. I'm attempting use this interface with some code like this:

Initialize(LPDISPATCH pDispArchivingControl) {
  LPOLESTR ptName = L"currentVaultId";
  HRESULT hr= pDispArchivingControl->GetIDsOfNames(IID_NULL, &ptName, 1, 
                         LOCALE_USER_DEFAULT, &dispID);
  // add parameters, etc
  hr = pDispArchivingControl->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, 
                   DISPATCH_METHOD, &dp, pvResult, NULL, NULL);
  // hr = 0x80020003 Member not found.
}

The first section, GetIDsOfNames(), does what I think it should, i.e. putting the names of methods from the program's documentation into ptName gives me different values in dispID - 15, 27, and so on.

The second section, Invoke(), always returns HRESULT 0x80020003 (Member not found).

I found some solutions listed here: HOWTO: Troubleshoot "Member Not Found" 0x80020003 Error. For resolution 1, I tried both DISPATCH_METHOD and DISPATCH_PROPERTYGET as the fourth parameter. Am I right in assuming 2 and 3 cannot apply to me as I am getting the values back in dispID? I'm not sure how to change these either.

I've kinda out of ideas now, and Google is not helping me any further - can anyone suggest what to do next?


UPDATE: This is what one of the methods looks like in oleview. I couldn't find it in the treeview but was able to open it with File > View TypeLib...

method seen in oleview

c++
com
asked on Stack Overflow Apr 18, 2012 by Colin Pickard • edited Apr 18, 2012 by Colin Pickard

1 Answer

1

The correct answer to this question, given by Hans Passant and Rup in the comments, is not to use late binding, but to #import the type library.

I put this in stdafx.h:

#import "ArchivingControl.tlb" raw_interfaces_only, raw_native_types, named_guids, auto_search

And this in my .cpp file:

ArchivingControl::IArchivingControlPtr JTArchivingControlPtr;
STDMETHODIMP CMyClass::Initialize(LPDISPATCH pDispArchivingControl)
{
   JTArchivingControlPtr = pDispArchivingControl;
   return S_OK;
}
STDMETHODIMP CMyClass::OtherFunction()
{
   BSTR pVaultId;
   JTArchivingControlPtr->get_currentVaultId(&pVaultId);
   return S_OK;
}

And now everything works nicely, plus I have way less code now - Thanks!

answered on Stack Overflow Apr 19, 2012 by Colin Pickard

User contributions licensed under CC BY-SA 3.0