Enumerate methods of a COM object (IDispatch) using ATL?

Using ATL (VS2008), how can I list the available methods available on this IDispatch interface ( IDispatch* )? I need to find a method with a specific name and, as soon as I have DISPID , the method is called (I know the parameters that the method takes). Ideally, I would like to do this using COM smart pointers ( CComPtr<> ).

Is it possible?

+6
c ++ com atl
source share
3 answers

You cannot list all available methods if the object does not implement IDispatchEx.

However, if you know the name of the method you want to call, you can use GetIDsOfNames to match the name with the corresponding DISPID.

 HRESULT hr; CComPtr<IDispatch> dispatch; DISPID dispid; WCHAR *member = "YOUR-FUNCTION-NAME-HERE"; DISPPARAMS* dispparams; // Get your pointer to the IDispatch interface on the object here. Also setup your params in dispparams. hr = dispatch->GetIDsOfNames(IID_NULL, &member, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (SUCCEEDED(hr)) { hr = dispatch->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, dispparams, &varResult, NULL, NULL); } 

Edit: For completeness, I suspect there is a way to poll the ITypeInfo2 interface (assuming there is a type library for the object), which you get from IDispatch :: GetTypeInfo for the list of methods, but I did not. See Another answer.

+7
source share

You can list the methods that IDispatch provides through type information. There are two ways to get type information:

Unfortunately, the IDispatch implementation is not required to provide information about the type of methods and properties that it implements.

If so, then the main enumeration includes calling ITypeInfo::GetTypeAttr to get the TYPEATTR for the interface and looking at the number of implemented methods ( cFuncs ) and variables ( cVars ) and going through them and calling ITypeInfo::GetFuncDesc() or ITypeInfo::GetVarDesc() Of course, there are many more details that you will have to deal with, as I can list here, but this should be a good starting point for your research.

Here's a good article explaining the process in more detail with the code in VB.Net.

+15
source share

Here is some code that does the enumeration (it inserts the [Dispatch ID] - [Method name] pairs into the map, but this is easy to change).

 /// /// \brief Returns a map of [DispId, Method Name] for the passed-in IDispatch object /// HRESULT COMTools::GetIDispatchMethods(_In_ IDispatch * pDisp, _Out_ std::map<long, std::wstring> & methodsMap) { HRESULT hr = S_OK; CComPtr<IDispatch> spDisp(pDisp); if(!spDisp) return E_INVALIDARG; CComPtr<ITypeInfo> spTypeInfo; hr = spDisp->GetTypeInfo(0, 0, &spTypeInfo); if(SUCCEEDED(hr) && spTypeInfo) { TYPEATTR *pTatt = nullptr; hr = spTypeInfo->GetTypeAttr(&pTatt); if(SUCCEEDED(hr) && pTatt) { FUNCDESC * fd = nullptr; for(int i = 0; i < pTatt->cFuncs; ++i) { hr = spTypeInfo->GetFuncDesc(i, &fd); if(SUCCEEDED(hr) && fd) { CComBSTR funcName; spTypeInfo->GetDocumentation(fd->memid, &funcName, nullptr, nullptr, nullptr); if(funcName.Length()>0) { methodsMap[fd->memid] = funcName; } spTypeInfo->ReleaseFuncDesc(fd); } } spTypeInfo->ReleaseTypeAttr(pTatt); } } return hr; } 
+10
source share

All Articles