多次调用编组的 COM 接口

Invoke marshalled COM interface multiple times

我正在编写一个 COM 对象供 JavaScript 使用。 JavaScript 代码依次在托管的 WebBrowserControl 中运行。我需要从 COM 对象触发一些事件到 JavaScript,这是 Dr. Dobbs

的优秀指南

例如 我的 *.idl

中有以下内容
IJSCallback
{
    void Listen(IDispatch* pJSMethod);
}

JavaScript 方法在 C++ 代码中作为 IDispatch* 接收,将被存储以供稍后从另一个线程调用它。 无论使用何种编组方法(CoMarshalInterThreadInterfaceInStreamIGlobalInterfaceTable),事件触发线程只能调用一次 JavaScript 函数。之后 IDispatch::Invoke() returns E_ACCESSDENIED!

样本JavaScript代码

var server = new ActiveXObject("prog_id")
var.Listen(function(ip_add) {
    // ip_add from COM object
});

C++ 线程非常简单。

// called from JavaScript
CMyObject::Listen(IDispatch* pJSMethod)
{
    // IStream* m_pStream;
    CoMarshalInterThreadInterfaceInStream(pJSMethod, IID_IDispatch, &m_pStream);
}

// called from internal C++ thread.
CMyObject::FireEvent()
{
    // IStream* m_pStream;
    // IDispatch* m_pJSMethod;
    CoGetInterfaceAndReleaseStream(m_pStream, IID_IDispatch, (LPVOID*)&m_pJSMethod);

    HSREULT hr = m_pJSMethod->Invoke(...); // hr = S_OK, call is received in JavaScript
    hr = m_pJSMethod->Invoke(...); // hr = E_ACCESSDENIED, call is not received in JavaScript
}

这是预期的行为吗?还是代码有问题?

已修复。如评论中所述,alert() 有效,但 document.writeln() 无效。那是因为document.writeln()重置了当前包含scripts元素的文档,使用document.createElement()document.createTextNode()和朋友修改当前加载的元素。

对于熟悉 HTML/JavaScript 的人来说,这可能是常识,对于我们其他人来说,这可能是一个真正的交易。