我遇到了一个问题,我很确定这个论坛能够帮助我解决这个问题。
我正在尝试向脚本添加一些自动化对象(通过单独的进程(ATL EXE 服务器)托管)。此外,我试图从我的 ATL EXE 脚本引擎中的这些自动化对象中接收事件。
为了实现这一点,我正在使用 CDispExSinkConnector,如http://www.codeproject.com/Articles/3326/Extending-the-Internet-Explorer-Scripting-Engine 中所述,我正在使用 IDispatchEx::GetDispID() 来创建脚本引擎中的新成员。创建成员 DISPID 后,我将使用 InvokeEx() 设置属性值。但是这些方法调用返回 RPC_E_SYS_CALL_FAILED。
注意 - 这里我从 OUT-OF-PROC IDispatch 指针中获取 IDispEx 指针。
更详细的描述:我在 ATL EXE 服务器中确实有一个由 CAxWindow 托管的 BrowserCtrl,我用它来为我的 MFC 客户端应用程序创建 HTML 插件。ATL EXE 服务器为 IWebBrowser2 方法提供包装器方法,以便我可以调用 IWebBrowser2Ptr->Navigate2() 之类的方法。
我还可以在此 ATL EXE 服务器中订阅 IWebBrowser2 事件,例如 OnDocumentComplete(....),并最终将这些事件转发到我的 MFC 客户端应用程序以在那里处理这些事件。下面是我的 ATL EXE 服务器 (BrowserCtrl) 的一些代码片段:
第一个是 CreateControl(),它创建 CAxWindow,创建 WebBrowser 控件并将控件托管在内部默认 CAxHostWindow 上。
STDMETHODIMP BrowserCtrl::CreateControl(ULONG hwndParent, LONG left,LONG top, LONG right, LONG bottom)
{
CRect rc(left, top, right, bottom);
// Create the AX host window. m_wndBrowserCtrl is CAxWindow object
HWND hwndAxHost = m_wndBrowserCtrl.Create(reinterpret_cast<HWND>(hwndParent), &rc, L"Shell.Explorer", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, ID_BROWSERCTRL );
//Obtain a pointer to the container object
CComQIPtr<IAxWinHostWindow> ptrWinHost;
HRESULT hr = m_wndBrowserCtrl.QueryHost(&ptrWinHost);
LPOLESTR lpszCLSID = NULL;
hr = StringFromCLSID(CLSID_WebBrowser, &lpszCLSID);
// Create the WebBrowser Ctrl
CComPtr<IUnknown> cpIUnknown = NULL;
hr = ptrWinHost->CreateControlEx(lpszCLSID, m_wndBrowserCtrl, NULL, &cpIUnknown, __uuidof(SHDocVw::DWebBrowserEvents2), reinterpret_cast<IUnknown*>(reinterpret_cast<DWebBrowserEvents2Impl*>(this)));
// Get the IWebBrowser2 interface pointer for the control
// CComQIPtr<IWebBrowser2> m_cpIBrowser;
m_cpIBrowser = cpIUnknown;
return S_OK;
}
//现在是 IWebBrowser2 方法的包装器方法
STDMETHODIMP BrowserCtrl::Navigate2(VARIANT *pwszUrl, VARIANT *Flags, VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers)
{
HRESULT hr = m_cpIBrowser->Navigate2(pwszUrl, Flags,TargetFrameName,PostData,Headers);
}
//现在是 IWebBrowser2 事件的事件处理程序:
void __stdcall BrowserCtrl::OnDocumentComplete(IDispatch* pDisp, VARIANT* pvaURL)
{
Fire_OnDocumentComplete(pDisp , pvaURL);// forwarding to the MGC client APP
}
现在的问题:
1.在 MFC 客户端应用程序和事件处理函数 OnDocumentComplete() 中,我执行以下操作:
void MFCClientApp::HandleDocumentComplete(LPDISPATCH pIDisp, VARIANT* pvaURL)
{
CComPtr<IDispatch> pDispDoc;
CComQIPtr<IDispatch> pScriptDisp;
CComQIPtr<IDispatchEx> pDispEx;
CComQIPtr<IHTMLDocument> pHTMLDoc;
CComQIPtr<IWebBrowser2> pWebBrowser;
if (pIDisp != NULL)
{
pWebBrowser = pIDisp;
//CComPtr<IDispatch> ptrIDisp;
//BOOL bResult = GetOPBrowser()->GetDisp(&ptrIDisp);
//pWebBrowser = ptrIDisp;
pWebBrowser->get_Document(&pDispDoc);
if (pDispDoc != NULL)
{
// Get the IDispatchEx interface
pHTMLDoc = pDispDoc;
if (pHTMLDoc != NULL)
{
pHTMLDoc->get_Script(&pScriptDisp);
pDispEx = pScriptDisp;
if (pDispEx != NULL)
{
CDispExSinkConnector pDispExSinkConnector = new CDispExSinkConnector();
Hr = pDispExSinkConnector->SetDispEx(pDispEx); // here the Hr returned is 0x80010100 “System Call Failed” i.e. RPC_E_SYS_CALL_FAILED
……
……..
………
}
这是 SetDispEx() 和内部相关函数:
void CDispExSinkConnector::SetDispEx(IDispatchEx *pDispEx)
{
CComBSTR bstrThisGuid("AC0B188C-6B55-408f-9E8C-821B9B5467CB"); // @!I8NIGNORE
HRESULT hr = m_pDispExGIT.Attach(pDispEx);//add it to the GIT Table
ASSERT(pDispEx);
// We need to add ourselves to the script engine
AddNamedObject(bstrThisGuid, this);
}
HRESULT CDispExSinkConnector::AddNamedObject(BSTR bsName, IDispatch *pDisp)
{
HRESULT hr = 0;
CComPtr<IDispatchEx> pDispEx;
GetDispEx(&pDispEx);
if(pDispEx == NULL)
return E_FAIL;
if(!bsName || SysStringLen(bsName) == 0 || !pDisp)
return E_INVALIDARG;
// Also, add our root objects into the script namespace
DISPID dispIdThis = 0;
hr = pDispEx->GetDispID(bsName, fdexNameEnsure | fdexNameCaseSensitive,&dispIdThis); // here the Hr returned is 0x80010100 “System Call Failed” i.e. RPC_E_SYS_CALL_FAILED
if (hr == DISP_E_UNKNOWNNAME)
…
..
}
请帮助我找出根本原因和解决此问题的解决方案。您的快速帮助将不胜感激。谢谢, SP