Windows – Out-of-proc COM服务器卡住
我使用out-of-proc COM服务器(COM单例“Engine”使用DECLARE_CLASSFACTORY_SINGLETON实现),它在STA(CComSingleThreadModel,_ATL_APARTMENT_THREADED)中工作.
COM服务器客户端: > ActiveScript(JScript),(我使用AddNamedItem传递引擎引用). BHO定期调用Engine :: dispatchEvent,Engine调用ActiveScript的JavaScript函数. 如果我打开两个BHO,当我调用ActiveScript的功能(使用IDispatch / Invoke)时,卡住了. 一些注释: >如果我没有将从BHO检索到的对象传递给ActiveScript(或将其替换为在Engine中创建的相同对象),一切都可以正常运行. 调用堆栈: > ntdll.dll!_ZwWaitForMultipleObjects@20() + 0x15 bytes ntdll.dll!_ZwWaitForMultipleObjects@20() + 0x15 bytes KernelBase.dll!_WaitForMultipleObjectsEx@20() + 0x100 bytes kernel32.dll!_WaitForMultipleObjectsExImplementation@20() + 0x8e bytes user32.dll!_RealMsgWaitForMultipleObjectsEx@20() + 0xe2 bytes ole32.dll!CCliModalLoop::BlockFn(void * * ahEvent,unsigned long cEvents,unsigned long * lpdwSignaled) Line 1222 C++ ole32.dll!ModalLoop(CMessageCall * pcall) Line 211 C++ ole32.dll!ThreadSendReceive(CMessageCall * pCall) Line 4979 C++ ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall(CMessageCall * * ppCall) Line 4454 + 0x6 bytes C++ ole32.dll!CRpcChannelBuffer::SendReceive2(tagRPCOLEMESSAGE * pMessage,unsigned long * pstatus) Line 4076 C++ ole32.dll!CCliModalLoop::SendReceive(tagRPCOLEMESSAGE * pMsg,unsigned long * pulStatus,IInternalChannelBuffer * pChnl) Line 899 + 0x17 bytes C++ ole32.dll!CAptRpcChnl::SendReceive(tagRPCOLEMESSAGE * pMsg,unsigned long * pulStatus) Line 583 + 0xd bytes C++ ole32.dll!CCtxComChnl::SendReceive(tagRPCOLEMESSAGE * pMessage,unsigned long * pulStatus) Line 734 + 0xa bytes C++ ole32.dll!NdrExtpProxySendReceive(void * pThis,_MIDL_STUB_MESSAGE * pStubMsg) Line 1932 C++ rpcrt4.dll!@NdrpProxySendReceive@4() + 0xe bytes rpcrt4.dll!_NdrClientCall2() + 0x144 bytes ole32.dll!ObjectStublessClient(void * ParamAddress,long Method) Line 474 + 0x8 bytes C++ ole32.dll!_ObjectStubless@0() Line 154 Asm ole32.dll!RemoteReleaseRifRefHelper(IRemUnknown * pRemUnk,int fReleaseRemUnkProxy,int fProcessingPostedMessage,OXIDEntry * pOXIDEntry,unsigned short cRifRef,tagREMINTERFACEREF * pRifRef,IUnknown * pAsyncRelease) Line 6770 + 0xc bytes C++ ole32.dll!RemoteReleaseRifRef(CStdMarshal * pMarshal,tagREMINTERFACEREF * pRifRef) Line 6694 C++ ole32.dll!CStdMarshal::DisconnectCliIPIDs() Line 3964 C++ ole32.dll!CStdMarshal::Disconnect(unsigned long dwType) Line 3273 C++ ole32.dll!CStdIdentity::~CStdIdentity() Line 312 C++ ole32.dll!CStdIdentity::`scalar deleting destructor'() + 0xd bytes C++ ole32.dll!CStdIdentity::CInternalUnk::Release() Line 767 C++ ole32.dll!IUnknown_Release_Proxy(IUnknown * This) Line 1773 C++ oleaut32.dll!_VariantClear@4() + 0xac9 bytes jscript.dll!VAR::Clear() + 0x50 bytes jscript.dll!GcAlloc::ReclaimGarbage() + 0xa2 bytes jscript.dll!GcContext::Reclaim() + 0x8e bytes jscript.dll!GcContext::CollectCore() - 0x72f bytes jscript.dll!GcContext::Collect() + 0x34 bytes jscript.dll!CScriptRuntime::Run() - 0x864f bytes jscript.dll!ScrFncObj::CallWithFrameOnStack() + 0xf3 bytes jscript.dll!ScrFncObj::Call() + 0x84 bytes jscript.dll!NameTbl::InvokeInternal() + 0x113 bytes jscript.dll!VAR::InvokeByDispID() + 0x73 bytes jscript.dll!CScriptRuntime::Run() + 0x1d89 bytes jscript.dll!ScrFncObj::CallWithFrameOnStack() + 0xf3 bytes jscript.dll!ScrFncObj::Call() + 0x84 bytes jscript.dll!NameTbl::InvokeInternal() + 0x113 bytes jscript.dll!VAR::InvokeByDispID() + 0x73 bytes jscript.dll!CScriptRuntime::Run() + 0x1d89 bytes jscript.dll!ScrFncObj::CallWithFrameOnStack() + 0xf3 bytes jscript.dll!ScrFncObj::Call() + 0x84 bytes jscript.dll!NameTbl::InvokeInternal() + 0x12c6 bytes jscript.dll!VAR::InvokeByDispID() + 0x73 bytes jscript.dll!NameTbl::GetVal() + 0x3b bytes 实施细节: // Engine (out of process COM singleton) class ATL_NO_VTABLE CEngine : public CComObjectRootEx<CComSingleThreadModel>,public CComCoClass<CEngine,&CLSID_Engine>,public IDispatchImpl<IEngine,&IID_IEngine,&LIBID_EngineLib,/*wMajor =*/ 1,/*wMinor =*/ 0> { DECLARE_CLASSFACTORY_SINGLETON(CEngine) STDMETHOD(dispatchEvent)(BSTR name,IDispatch* pEvent,VARIANT_BOOL* pbSuccess) { // pEvent is CPropertyStore instance ActiveScriptDispatch.Invoke1(L"FuncName",pEvent,&varResult); } } // BHO class CPropertyStore : public CComObjectRootEx<CComSingleThreadModel>,public CComCoClass<CPropertyStore,&CLSID_NULL>,public IDispatch { BEGIN_COM_MAP(CPropertyStore) COM_INTERFACE_ENTRY(IUnknown) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() BOOL SetProperty(CString strName,VARIANT *value) { // Store value in CAtlArray } // IDispatch impl STDMETHOD(GetTypeInfoCount)(UINT *pctinfo); STDMETHOD(GetTypeInfo)(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); STDMETHOD(GetIDsOfNames)(REFIID riid,LPOLESTR *rgszNames,UINT cNames,DISPID *rgDispId); STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); } class ATL_NO_VTABLE CBHO : public CComObjectRootEx<CComSingleThreadModel>,public CComCoClass<CBHO,&CLSID_BHO>,public IObjectWithSiteImpl<CBHO>,public IDispatchImpl<IBHO,&IID_IBHO,&LIBID_Lib,/*wMinor =*/ 0>,public IDispEventImpl<1,CBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1,0> { void onEvent(...) { if(m_pEngine == NULL && SUCCEEDED(m_pEngine.CoCreateInstance(CLSID_Engine))) { CComObject<CPropertyStore> *pEvent = NULL; HRESULT hRes = CComObject<CPropertyStore>::CreateInstance(&pEvent); CComVariant varEvent(pEvent); CComVariant varName(L"EventName"); CComVariant varResult; m_pEngine.Invoke2(L"dispatchEvent",&varName,&varEvent,&varResult); } } }
您的BHO(浏览器助手对象)位于单线程公寓中.在另一个STA(不同的线程)上的一个对象的STA中的每个COM调用在消息队列中被消息排序,然后在方法调用中“转换”.
这通常不是问题,因为大多数时间的呼叫是由单线程的GUI触发的. COM电话等待WM_LBUTTONUP消息等等. 在你的情况下会发生什么是在服务onEvent时,你的BHO对象发送到另一个线程,在另一个进程中,你的进程外COM对象.当您尝试从MTA appartment回调原始对象时,Windows邮件将在托管它的Internet Explorer进程中发布到您的BHO STA线程.但消息队列仍然在忙于服务原始请求. 这解释了你的僵局,以及为什么通过一个字符串的作品. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 无法在Windows中的Docker内启动TensorFlow
- Windows API一日一练 4 MessageBox函数
- windows-server-2008 – Windows 2008 Server上的死网关检测
- windows-8 – WinRT和托管之间的映射如何工作?
- 在Windows Server 2008上挂载ISO
- xaml – 在Windows 10 UWP中具有自定义附加属性的自适应触发
- 那里有没有工作和完整的1-Wire .NET库?
- windows-phone-7 – WP7 Marketplace中XAP的文件大小限制是
- mschart – Microsoft图表控件图例项目排序
- windows-server-2003 – 防止在共享上删除/移动文件夹
- 如何在Windows Mobile 6下将Flash游戏嵌入到Wind
- Win10常用快捷键
- 在Windows上安装和运行hadoop 2.2的文档
- windows-server-2008 – 修改Active Directory连
- windows-server-2003 – 如何获得创建全文索引的
- Windows Server 2016-Win Ser 2016新增功能
- 键盘语言更改在Windows 7上的PhpStorm中不起作用
- installer – 将摘要信息添加到WiX生成的MSI
- win-universal-app – 如何在Windows 10 UWP中实
- Windows Octave无法从剪贴板粘贴文本?