6

It's a bit difficult to explain my exact scenario, but I will try:

I'm inspecting a DOM interface that was created via late binding, and at some point selecting a range which returns an interfaced OleVariant Element (this I know for sure).

I was expecting an IHTMLElement2 but it is not (I get an exception that the object does not have a tagName property). Which made me later suspect (not tested yet) its a Node element (which has nodeName property) - but I don't want to guess, and ask:

if Supports(IDispatch(v), IWhatEver1)... else if Supports(IDispatch(v), IWhatEver2)...

I don't know which interface it supports. how do I know the interface name/guid from an OleVariant interface object?

The problem is not only specific to DOM, if for example, I have an OleVariant that was created via:

SomeObject := CreateOleObject('WinHttp.WinHttpRequest.5.1'); 
or
SomeObject := CreateOleObject('Msxml.ServerXMLHTTP'); 
or
SomeObject := CreateOleObject('Msxml.XMLHTTP'); 
etc...

v := SomeObject;

How do I later know which IDispatch is behind v?

I hope the question is clear.


Seems like IE11 changed its behavior when using FEATURE_BROWSER_EMULATION = 8000 for my application -> when you use TWebBrowser in design mode and select a range vElement (the Element in the selected Range) returns as JScriptTypeInfo... I don't know why, and I don't know still how to deal with this b.s, but at least I know which Interface I have!

Here is the code I used to examine the Element:

if SysUtils.Supports(IUnknown(vElement), IDispatch, LDispatch) then
  begin
    debug('vElement Supports IDispatch');
    if LDispatch.GetTypeInfo(0, 0, ti) = S_OK then
      if ti.GetDocumentation(MEMBERID_NIL, @pbstrName, @pbstrDocString, nil, nil) = S_OK then
        debug(pbstrName + ';' + pbstrDocString); // <- JScriptTypeInfo;JScript TypeInfo
  end;
kobik
  • 21,001
  • 4
  • 61
  • 121
  • I don't really understand. In your final example, you assign a IWinHttpRequest to v. Well, v will always be IWinHttpRequest. It cannot ever change type. If you call a method and don't know what type object it returns I suggest you read the documentation to find out. – David Heffernan Dec 27 '13 at 09:56
  • 2
    @DavidHeffernan: "read the documentation". But often the documentation is inadequate. E.g. the documentation and TLB of the best known PDF product are riddled with interfaces with member functions which return an IDispatch interface, from which you have to retrieve another type of interface in the TLB in order to use it. I could imagine the OP's problem is similar: "How do I tell what is behind this opaque IDispatch?" If you see what I mean ... – MartynA Dec 27 '13 at 10:23
  • @MartynA That may be so. Sometimes the documentation is fine and the programmer doesn't read it properly. Plenty of ways for things to go wrong. The final section of the question does suggest that there may be some confusion on the part of the asker. – David Heffernan Dec 27 '13 at 10:30
  • @kobik This is a pure win32/com question. If I were you I'd make the Q many neutral and use only winapi tag. Using delphi tag will scare away some com experts. – David Heffernan Dec 27 '13 at 11:06
  • @David, I will think about your suggestion. I'm tempted to add the c++ tag ;) I have made an edit an I hope now its clearer. MartynA described my exact situation, there is no confusion on my part. – kobik Dec 27 '13 at 12:06
  • I was confused by the idea that the object in v might change type. If the docs are no help, use ITypeInfo to reverse engineer what this thing is! – David Heffernan Dec 27 '13 at 12:11
  • 2
    Your options to get ProgID for an interface pointer you are holding: [How to get a COM object Coclass's progid at runtime](http://stackoverflow.com/questions/13362113/c-how-to-get-a-com-object-coclasss-progid-at-runtime/13362541#13362541) and also [Getting GUID of coclass object using pointer to interface it implements](http://stackoverflow.com/questions/10800595/com-getting-guid-of-coclass-object-using-pointer-to-interface-it-implements/10800679#10800679) – Roman R. Dec 27 '13 at 12:17
  • 2
    @RomanR, OK. Once I have `ITypeInfo` of `ProvideClassInfo`, How do I obtain the CLSID? (`ProvideClassInfo2` has `GetGUID` but `ProvideClassInfo` does not) – kobik Dec 27 '13 at 13:29

1 Answers1

5

COM interfaces do not provide any generic way to retrieve their CLSID or ProgID. You are expected to know what sort of object you are dealing with. The documentation for the COM object should tell you that information.

If for whatever reason, you have an IDispatch whose type you do not know, you may be able to work it out by inspection using IDispatch.GetTypeInfo. Once you have the ITypeInfo reference, call ITypeInfo.GetDocumentation passing MEMBERID_NIL to find out information on the object's class.

As for the example in the second part of your question, again you are expected to know what type of object you have. You know that information at the point where you call CreateOleObject and you are simply expected to remember.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490