Retrieve DISPID of outgoing dispinterface member
See the question and my original answer on StackOverflowIf the object is "quite standard", then it should be possible.
From the object/IDispatch interface, you should be able to get to the TLB (type library). From the type library, you should be able to browse all coclasses, and get interfaces that these coclasses implement. You need to get to interface you have the IID for, browse the member and get the one you're interested.
There are many cases where this just won't work. Here is a console sample I've put up that works with a shell object. I've written it in C# because it's easier, but there's nothing you can't do with a decent language. I've used an old TLBINF32.DLL com utility library (only x86 unfortunately) I talk about in my answer to this question here on SO: How to read COM TypeLib with C# or C++?
static void Main(string[] args)
{
// create a sample object every one has
object o = Activator.CreateInstance(Type.GetTypeFromProgID("shell.application")); // for example
TLIApplication app = new TLIApplication();
// not sure, but I believe in pure COM it's calling IDispatch::GetTypeInfo & ITypeInfo::GetContainingTypeLib
TypeLibInfo tli = app.InterfaceInfoFromObject(o).Parent;
// this is the guid for DShellFolderViewEvents
int dispid = GetDispId(tli, new Guid("{62112AA2-EBE4-11CF-A5FB-0020AFE7292D}"), "SelectionChanged");
Console.WriteLine("dispid:" + dispid); // should display 200
}
public static int GetDispId(TypeLibInfo tlb, Guid diid, string memberName)
{
// browse all coclasses
// in pure COM this is ITypeLib::GetTypeInfo
foreach (CoClassInfo ti in tlb.CoClasses)
{
// browse all interfaces in those coclasses
// in pure COM this is ITypeInfo::GetRefTypeOfImplType
foreach (InterfaceInfo itf in ti.Interfaces)
{
// only select [source] interfaces (events)
// this test is optional since the diid is unique
// in pure COM this is ITypeInfo::GetImplTypeFlags
if (((ImplTypeFlags)itf.AttributeMask & ImplTypeFlags.IMPLTYPEFLAG_FSOURCE) != ImplTypeFlags.IMPLTYPEFLAG_FSOURCE)
continue;
if (new Guid(itf.GUID) == diid)
{
// in pure COM this is ITypeInfo::GetTypeAttr & ITypeInfo::GetFuncDesc
foreach (MemberInfo mi in itf.Members)
{
if (mi.Name == memberName)
return mi.MemberId;
}
}
}
}
return -1;
}