Note that there are some explanatory texts on larger screens.

plurals
  1. POExposing COM events to VBScript (ATL)
    primarykey
    data
    text
    <p>I have built a COM server DLL in C++ with ATL by using the "ATL simple object" wizard. I followed Microsoft's <a href="http://code.msdn.microsoft.com/windowsdesktop/ATLDllCOMServer-09df00e4" rel="nofollow noreferrer">ATLDLLCOMServer</a> example. Everything works well except for one thing: <strong>I do not receive COM events in VBScript</strong>. I do receive the events in C#. I had events working in VBScript in an earlier MFC-based implementation as ActiveX control.</p> <p>My control is defined like this:</p> <pre><code>class ATL_NO_VTABLE CSetACLCOMServer : public CComObjectRootEx&lt;CComSingleThreadModel&gt;, public CComCoClass&lt;CSetACLCOMServer, &amp;CLSID_SetACLCOMServer&gt;, public IConnectionPointContainerImpl&lt;CSetACLCOMServer&gt;, public CProxy_ISetACLCOMServerEvents&lt;CSetACLCOMServer&gt;, public IDispatchImpl&lt;ISetACLCOMServer, &amp;IID_ISetACLCOMServer, &amp;LIBID_SetACLCOMLibrary, /*wMajor =*/ 1, /*wMinor =*/ 0&gt;, public IProvideClassInfo2Impl&lt;&amp;CLSID_SetACLCOMServer, &amp;DIID__ISetACLCOMServerEvents, &amp;LIBID_SetACLCOMLibrary&gt; /* Required for event support in VBS */ { public: BEGIN_COM_MAP(CSetACLCOMServer) COM_INTERFACE_ENTRY(ISetACLCOMServer) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IConnectionPointContainer) COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2) END_COM_MAP() BEGIN_CONNECTION_POINT_MAP(CSetACLCOMServer) CONNECTION_POINT_ENTRY(__uuidof(_ISetACLCOMServerEvents)) END_CONNECTION_POINT_MAP() [...] </code></pre> <p>In VBScript I use the COM object like this:</p> <pre><code>set objSetACL = WScript.CreateObject("SetACL.SetACL", "SetACL_") ' Catch and print messages from the SetACL COM server which are passed (fired) as events. ' The name postfix of this function (MessageEvent) must be identical to the event name ' as defined by SetACL. ' The prefix (SetACL_) can be set freely in the call to WScript.CreateObject sub SetACL_MessageEvent (Message) WScript.Echo Message end sub </code></pre> <p>The relevant parts of the IDL look like this:</p> <pre><code>[ object, uuid(E1B57CA5-FD7F-4304-BC0A-8BEBDE231D53), dual, nonextensible, pointer_default(unique), helpstring("SetACL COM Interface") ] interface ISetACLCOMServer : IDispatch { }; [ uuid(00D4DCD3-02B9-4A71-AB61-2283504620C8), version(1.0), helpstring ("SetACL Type Library") ] library SetACLCOMLibrary { importlib("stdole2.tlb"); [ uuid(35F76182-7F52-4D6A-BD6E-1317345F98FB), helpstring ("SetACL Event Interface") ] dispinterface _ISetACLCOMServerEvents { properties: methods: [id(1), helpstring("Receives string messages that would appear on the screen in the command line version")] void MessageEvent([in] BSTR message); }; [ uuid(13379563-8F21-4579-8AC7-CBCD488735DB), helpstring ("SetACL COM Server"), ] coclass SetACLCOMServer { [default] interface ISetACLCOMServer; [default, source] dispinterface _ISetACLCOMServerEvents; }; }; </code></pre> <p>The <strong>problem</strong>: SetACL_MessageEvent never gets called.</p> <p>What I have tried:</p> <ul> <li>After reading <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;200839" rel="nofollow noreferrer">this KB article</a> I added the implementation of IProvideClassInfo2, but that did not help.</li> <li>This <a href="http://support.microsoft.com/kb/166480" rel="nofollow noreferrer">FAQ</a> mentions that outgoing interface should not defined as a dual interfaces. I removed the "dual" from my interface definition, but that did not help.</li> <li>I found <a href="https://stackoverflow.com/questions/9170054/atl-com-events-for-javascript">this SO question</a> that seems to describe a similar problem. An answer was never given, only a workaround.</li> </ul> <p><strong>UPDATE 1:</strong></p> <p>I know now where it is failing, but not why: in the fire event method in _ISetACLCOMServerEvents_CP.h the call to Invoke fails with E_UNEXPECTED. This is the line:</p> <pre><code>hr = pConnection-&gt;Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &amp;params, NULL, NULL, NULL); </code></pre> <p><strong>Solution:</strong></p> <p>The problem was that I called the event firing function from a background thread in the COM object, in other words from the wrong apartment.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload