Enumerate COM object (IDispatch) methods using ATL?
You can't enumerate all the available methods unless the object implements IDispatchEx.
However, if you know the name of the method you want to call, you can use GetIDsOfNames to map the name to the proper 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 interrogate the ITypeInfo2 interface (assuming there is a type library for the object) that you get from IDispatch::GetTypeInfo for a list of methods, but I've not done it. See the other answer.
Implement COM IDispatch without ATL
If the interface is properly defined in the IDL and compiled into a type library, implementing IDispatch
via the type library's ITypeInfo
is quite feasible as it's mostly delegating. The interesting part is ITypeInfo::Invoke
which relies upon correct C++ v-table layout:
public class CComClass: public IDualInterface
{
// ...
// implementing IDualInterface
ITypeInfo* m_pTypeInfo // can be obtained via ITypeLib::GetTypeInfoOfGuid for the GUID of IDualInterface
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT* pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
if (0 != itinfo)
return E_INVALIDARG;
(*pptinfo = m_pTypeInfo)->AddRef();
return S_OK;
}
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
{
return m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
}
STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
return m_pTypeInfo->Invoke(static_cast<IDualInterface*>(this), dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
}
}
I've used a similar approach to create a script-callable wrapper for MSHTML DOM objects to bypass scripting security restrictions.
So where do you get the ITypeInfo from? Essentially you get it by:
- Write an IDL file which declares your interface as a dual interface. It has to be a dual interface, as that is how the
ITypeInfo
implementation knows which function to invoke - it cannot just invoke the C++ functions directly on your class because C++ has no reflection and because it is language neutral. Therefore it can only delegate theInvoke
call to another method declared in the type library. - Compile the IDL to a header file and type library as part of the build process
- The header file produced from the IDL defines the interface, which your implementing class must inherit from. Once you have implemented all the methods you are good to go. (For development start by making them all return
E_NOTIMPL
then implement them one by one) - Install the Type Library, either to the destination directory, or as a resource in the EXE/DLL. It will need to be registered by calling
RegisterTypeLib
. If it is embedded as a resource, you should call this from yourDllRegisterServer
implementation. - Load the type library when the first instance of your object is created, using
LoadTypeLib
. This gives you anITypeLib
- Get the ITypeInfo you need using
GetTypeInfoOfGuid
.
Chaining methods of ATL/COM objects
Something like this:
interface IMyInterface {
HRESULT DoSomething([in] long someParam, [out, retval] IMyInterface** ret);
HRESULT DoSomethingElse([out, retval] IMyInterface** ret);
};
Scripting clients should be able to do myObj.DoSomething(42).DoSomethingElse()
How I can enumerate the COM Object Members like interfaces, properties and methods?
You need to be more specific. There are two ways to interpret your question.
One is that you have a COM component (e.g. some library), and you want to programmatically enumerate interfaces/properties/methods of that. Usually (but not always), COM components come with a type library that contains full metainformation about all this - it's either embedded into the COM .exe or .dll, or is a separate .tlb file. In any case, if the COM component is properly registered in the system (e.g. using regsvr32), then COM provides a standard API to retrieve that type information, centered around ITypeLib and ITypeInfo interfaces.
Another interpretation is that you get a reference to a particular COM object, and you need to enumerate all methods/properties on that and/or invoke them by computed name, like Java or C# reflection, or Delphi RTTI. If so, then it is only possible if the COM object implements IDispatch interface, which allows you to do all of the above.
How to create anonymous IDispatch functions with ATL?
By default ATL creates "auto-dual" COM classes. They support both early binding and IDispatch. You'll see IDispatchImpl<> in their inheritance list. You declare the dispid in the IDL. No extra work is required.
Create A COM object inside another COM object
Use the ATL wizard to create the implementation of ISystemCmds. Then create the object through normal CoCreateInstance, or use the CComObject<> template (see method CreateInstance) if you need to initialize the object in a way that ISystemCmds does not support. Be aware that CComObject<>::CreateInstance() does not AddRef() your object like QueryInterface() and CoCreateInstance() do. AddRef the object before passing it along!
How to Pass an ATL com object from c++ to c#
Try to pass raw IUnkown*
pointer to C# and then use Marshal.GetObjectForIUnknown
to convert IntPtr
to object
and then cast this object to Icompte
. You will need to add reference to the corresponding TypeLib into C# project to be able to perform such a cast.
Creating an ATL COM object that implements a specific interface
It's much more automatic than the other answers here are suggesting. All the boilerplate code is written for you by Visual Studio.
You're lucky you have the .idl, it's by far the most conveninent, I think.
You could paste the contents of the .idl file into your ATL COM project's existing .idl file, which would give you access to the declarations in it. For example, something like this could be pasted into an IDL file:
[
object,
uuid(ecaac0b8-08e6-45e8-a075-c6349bc2d0ac),
dual,
nonextensible,
helpstring("IJim Interface"),
pointer_default(unique)
]
interface IJim : IDispatch
{
[id(1), helpstring("method SpliceMainbrace")] HRESULT SpliceMainbrace(BSTR* avast);
};
Then in Class View, right click your class and choose Add | Implement Interface
.
Notice that in this dialog, you can actually browse for a .tlb file, but I think it's better to have plain-text source for these things, for version control and the like.
Pick IJim
from the list, press the >
button to add it to the list to be implemented. Press Finish.
Visual Studio will add this to your class (along with a bunch of other crap to make it work):
// IJim Methods
public:
STDMETHOD(SpliceMainbrace)(BSTR * avast)
{
// Add your function implementation here.
return E_NOTIMPL;
}
Enumerating all IDispatch implementing objects on a machine
That's a very odd request. The rub is in the "all" stipulation. Simple enumeration through the HKCR\Typelib key and LoadTypeLib() isn't enough, a COM server is not required to publish a type library. You would actually have to CoCreateInstance() the coclass and QueryInterface for IDispatch. Not only is this slow, it is also risky.
You might get a better answer if you explain why you would actually contemplate doing something like this. Calling IDispatch::Invoke() without having some kind of idea what the arguments mean or what the side-effects might be is a recipe for disaster. Stay away from method names like "ReformatDrive".
Related Topics
Can a C Compiler Rearrange Stack Variables
Best C++ Matrix Library for Sparse Unitary Matrices
Getting Actual File Name (With Proper Casing) on Windows
How to Make Camera Follow a 3D Object in Opengl
What Exactly Is the Purpose of the (Asterisk) in Pointers
Floating Point to Binary Value(C++)
Opencv Cvsaveimage Jpeg Compression Factor
Stateful Functors & Stl:Undefined Behaviour
C++ Arrays as Function Arguments
Why Do You Need to Append an L or F After a Value Assigned to a C++ Constant
Msvc Equivalent of _Attribute_ ((Warn_Unused_Result))
Template Metaprogramming: (Trait For) Dissecting a Specified Template into Types T<T2,T3 N,T4, ...>
Why Does Std::Map Not Have a Const Accessor
How to Know When a New Usb Storage Device Is Connected in Qt
C++11 Random Number Distributions Are Not Consistent Across Platforms -- What Alternatives Are There