Why does WScript.ConnectObject not always work?
I've had a tiny handful of entries in my VBScript quiz. I know from my logs that 2600+ people have read it. Come on people, there are fabulous prizes at stake here! Go for it!
I'm going to keep the contest open until Friday morning, at which point I'll start posting answers and analysis.
****************************************************
Earlier today someone asked me why it is that sometimes
WScript.ConnectObject does not connect an object to an event sink even if the object sources events. That reminded me that back in June I said that I'd explain this at some point, and I never did.
WScript.ConnectObject
only works if the object implements IProvideClassInfo or IProvideMultipleClassInfo. Not all objects do.
Why?
An object can implement multiple interfaces both incoming and outgoing. Incoming interfaces are the interfaces you call an object on. Outgoing interfaces are interfaces that they call you on. That's how events work: you tell the object that you want a particular method to be called on a particular outgoing interface when a particular event occurs.
Each interface supported by an object, whether incoming or outgoing, can have its own interface typeinfo describing it. For a given object all these interfaces are "summarized" by one "parent" type info called the "coclass type info". Once you have the coclass type info, you can figure out everything about the object's incoming and outgoing interfaces.
Clearly, in order to build an event sink for an object, you need to know what events the event source is going to source! You need the outgoing interface typeinfo, or, equivalently, the coclass typeinfo.
The flaw in the design of the automation interfaces is this: given an
IDispatch object, there is no way to discover what its coclass typeinfo is! You can get a type info for the dispatch interface -- that is, the incoming call interface -- by calling GetTypeInfo. But there is no way to get the coclass type info, and therefore no way to determine what the outgoing interfaces are on the object, and therefore no way to bind its events.
When that omission was realized,
IProvideClassInfo was invented. (And for aggregate objects, which may have aggregated multiple coclasses, IProvideMultipleClassInfo was invented.) IProvideClassInfo returns the coclass type info. That's why WScript.ConnectObject requires IProvideClassInfo -- it just has the object and knows nothing about its class.
You may then wonder how it is that
WScript.CreateObject does event binding on objects that do not implement IProvideClassInfo. That's easy -- WScript.CreateObject is given enough information to find the coclass type info. WScript.CreateInstance is passed the progid. It uses that to look up the class id in the registry. It obtains the incoming interface typeinfo from the newly-created dispatch object, obtains the typelibrary from the typeinfo, and searchs the typelibrary for a coclass type info which matches the class id.
This also explains how it is that Visual Basic can do event binding on objects which do not implement
IProvideClassInfo. VB has compile-time information about the progid of the object and can look up the outgoing interface in the same way.
We considered creating another version of WScript.ConnectObject which took a classid or progid, but we decided that it wouldn't be useful in very many situations, and would be confusing and hard to document well.
Comments
- Anonymous
February 15, 2005
The comment has been removed - Anonymous
February 16, 2005
The comment has been removed - Anonymous
February 18, 2005
Hopefully I know how to subscribe for a CLR event in JScript.NET (but I wish there was a language spec stating that in MSDN, mostly it's written here and there "you can only listen to the events, you cannot source them", but no idea given on how to do this listening).
But well, is JS.NET capable of subscribing to COM events? Directly, I mean, not using the sink as AxHost does.
Also, what about firing the .NET events? I can fire an event if I extend a class that has them defined (by implementing the add_ and remove_ functions), but can I introduce my own ones from a scratch some way? - Anonymous
February 19, 2005
Good questions. I'll write a blog entry on that some time. - Anonymous
September 09, 2005
Back in February I posted a bit about how script hosts such as Windows Script Host dynamically hook... - Anonymous
June 26, 2006
Would it be possible for Microsoft to actually update the product documentation such as http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/bbd53502-bcf9-4bcd-a8bc-ae723a46534d.asp to reflect the fact that the software does not work as expected????
That's be nice - documentation that's accurate.