0

我们有一个应用程序在主线程或不同线程(异步)中运行一些 COM 托管,我们希望通过使用标准 ConnectionPoint 接口连接到这个(可连接)对象以获取其事件。

直到 Windows 10 SP 1903,它确实有效。

但是,在“1903 更新”中测试应用程序 IConnectionPoint->Advise() 时,当代码在与起始线程不同的线程中运行时,CONNECT_E_CANNOTCONNECT 失败 - 在调用 Advise() 时,事件服务器会询问很多我不支持的接口,我应该只支持 IUnknown、IDispatch 和事件接口。

整个东西在非STA主线程运行的时候查询的接口很多,<1903的少,1903的有这些:

clsEventSink(Dialog_)::QueryInterface(IID_IAgileObject) failed
clsEventSink(Dialog_)::QueryInterface({2132B005-C604-4354-85BD-8F2E24181B0C}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IMarshal) failed
clsEventSink(Dialog_)::QueryInterface(IID_INoMarshal) failed
clsEventSink(Dialog_)::QueryInterface(IID_IAgileObject) failed
clsEventSink(Dialog_)::QueryInterface({2132B005-C604-4354-85BD-8F2E24181B0C}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IMarshal) failed
clsEventSink(Dialog_)::QueryInterface({0000001B-0000-0000-C000-000000000046}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IUnknown) succeeded
clsEventSink::AddRef(1)
clsEventSink::AddRef(2)
clsEventSink(Dialog_)::QueryInterface(IID_IStdMarshalInfo) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({00000040-0000-0000-C000-000000000046}) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IAgileObject) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({77DD1250-139C-2BC3-BD95-900ACED61BE5}) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({BFD60505-5A1F-4E41-88BA-A6FB07202DA9}) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface(IApplicationFrame) failed
clsEventSink(Dialog_)::QueryInterface(IApplicationFrameManager) failed
clsEventSink(Dialog_)::QueryInterface(IApplicationFrameEventHandler) failed
clsEventSink(Dialog_)::QueryInterface(IStreamGroup) failed
clsEventSink(Dialog_)::QueryInterface(iaudiodevicegraph) failed
clsEventSink(Dialog_)::QueryInterface({4F4F92B5-6DED-4E9B-A93F-013891B3A8B7}) failed
clsEventSink(Dialog_)::QueryInterface({9BC79C93-2289-4BB5-ABF4-3287FD9CAE39}) failed
clsEventSink(Dialog_)::QueryInterface({1868091E-AB5A-415F-A02F-5C4DD0CF901D}) failed
clsEventSink(Dialog_)::QueryInterface({11456F96-09D1-4909-8F36-4EB74E42B93E}) failed
clsEventSink(Dialog_)::QueryInterface(IEUserBroker) failed
clsEventSink(Dialog_)::QueryInterface({35BD3360-1B35-4927-BAE4-B10E70D99EFF}) failed
clsEventSink(Dialog_)::QueryInterface(IVerbStateTaskCallBack) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({03FB5C57-D534-45F5-A1F4-D39556983875}) failed
clsEventSink(Dialog_)::QueryInterface({2C258AE7-50DC-49FF-9D1D-2ECB9A52CDD7}) failed
clsEventSink(Dialog_)::QueryInterface(IExternalConnection) failed
clsEventSink(Dialog_)::QueryInterface({4C1E39E1-E3E3-4296-AA86-EC938D896E92}) failed
clsEventSink(Dialog_)::QueryInterface({AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}) failed

然后 Advise() 放弃并返回上面提到的错误代码。因此,我无法在与应用程序的主 STA 线程不同的线程中创建事件接收器。

更明确地说,我们有一个关系管理器应用程序,它希望在不同的线程中显示一个非模态对话框,即

  • 应用程序创建一个新线程,该线程
  • 托管然后执行的脚本,
  • 该脚本调用应用程序的一个方法(作为标准 OLE 服务器),该方法创建管理对话窗口的 OLE 控件(使用 CoCreateInstance 等)[在我假设的主 STA 线程中创建]
  • 然后脚本连接脚本线程中的控件(使用 Advise() 等),以便对话框控件可以使用脚本主机中的对象触发事件

因此,如果要进行编组,我现在的猜测是对话控件内部必须编组我传递给 Advise() 的指针,至少这是我在 WWW 的深度读到的。由于我们在这里不做任何事情,它使用标准编组器,编组正在通过 combase!CStdMarshal:CreateStub() 完成(或至少尝试这样做),这似乎不再成功。当我被要求提供一个接口(上图)时的堆栈是

>   cmSC24.dll!clsEventSink::QueryInterface(const _GUID & riid={...}, void * * ppv=0x04c5cf60) Line 121 C++
combase.dll!CStdMarshal::CreateStub(tagIPIDEntry * pEntry=0x0b87c388, IRpcStubBuffer * * ppStub=0x04c5d030, void * * ppv=0x04c5d034, int * pfNonNDR=0x04c5d038, IUnknown * pUnkUseInner=0x00000000) Line 6628   C++
[Inline Frame] combase.dll!CStdMarshal::ConnectSrvIPIDEntry(tagIPIDEntry *) Line 2600   C++
combase.dll!CStdMarshal::MarshalServerIPID(const _GUID & riid={...}, unsigned long cRefs=5, unsigned long mshlflags=0, tagIPIDEntry * * ppEntry=0x04c5d070, IUnknown * pUnkUseInner=0x00000000, PreventRundownBiasContainer * pBiasContainer=0x00000000, bool bApplyDirectMarshalingMitigation=false) Line 1539 C++
[Inline Frame] combase.dll!CStdMarshal::MarshalIPID(const _GUID &) Line 1391    C++
combase.dll!CRemoteUnknown::RemQueryInterface(const _GUID & ripid={...}, unsigned long cRefs=5, unsigned short cIids=1, _GUID * iids=0x0d7820fc, tagREMQIRESULT * * ppQIResults=0x04c5d4c8) Line 510    C++
rpcrt4.dll!_Invoke@12() Unknown
rpcrt4.dll!_NdrStubCall2@16()   Unknown
combase.dll!CStdStubBuffer_Invoke(IRpcStubBuffer * This=0x0e17f408, tagRPCOLEMESSAGE * prpcmsg=0x0e1e38b0, IRpcChannelBuffer * pRpcChannelBuffer=0x0e0bc540) Line 1531  C++
[Inline Frame] combase.dll!InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_ee1df801181086a03fa4f8f75bd5617f>::operator()() Line 1385 C++
combase.dll!ObjectMethodExceptionHandlingAction<<lambda_ee1df801181086a03fa4f8f75bd5617f> >(InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_ee1df801181086a03fa4f8f75bd5617f> action={...}, ObjectMethodExceptionHandlingInfo * pExceptionHandlingInfo=0x04c5d61c, ExceptionHandlingResult * pExceptionHandlingResult=0x04c5d600, void *) Line 87    C++
[Inline Frame] combase.dll!InvokeStubWithExceptionPolicyAndTracing(IRpcStubBuffer * pMsg=0x0e1e38b0, tagRPCOLEMESSAGE *) Line 1383  C++
combase.dll!DefaultStubInvoke(bool bIsAsyncBeginMethod=false, IServerCall * pServerCall=0x0dcc3f64, IRpcChannelBuffer * pChannel=0x0e0bc540, IRpcStubBuffer * pStub=0x0e17f408, unsigned long * pdwFault=0x04c5da08) Line 1452  C++
[Inline Frame] combase.dll!SyncStubCall::Invoke(IServerCall *) Line 1509    C++
[Inline Frame] combase.dll!SyncServerCall::StubInvoke(IRpcChannelBuffer *) Line 825 C++
[Inline Frame] combase.dll!StubInvoke(tagRPCOLEMESSAGE * pMsg=0x80004002, CStdIdentity * pStdID=0x0e2381e8, IRpcStubBuffer *) Line 1734 C++
combase.dll!ServerCall::ContextInvoke(tagRPCOLEMESSAGE * pMessage=0x0e1e38b0, IRpcStubBuffer * pStub=0x0e17f408, CServerChannel * pChannel=0x0e0bc540, tagIPIDEntry * pIPIDEntry=0x0d8e8d98, unsigned long * pdwFault=0x04c5da08) Line 1418 C++
[Inline Frame] combase.dll!CServerChannel::ContextInvoke(tagRPCOLEMESSAGE *) Line 1327  C++
[Inline Frame] combase.dll!DefaultInvokeInApartment(tagRPCOLEMESSAGE *) Line 3352   C++
combase.dll!ReentrantSTAInvokeInApartment(tagRPCOLEMESSAGE * pMsg=0x0e1e38b0, unsigned long dwCallCat=1, bool bIsTouchedASTACall=false, IRpcStubBuffer * pStub=0x0e17f408, CServerChannel * pChnl=0x0e0bc540, tagIPIDEntry * pIPIDEntry=0x0d8e8d98, unsigned long * pdwFault=0x04c5da08) Line 112   C++
combase.dll!AppInvoke(ServerCall * pServerCall=0x0dcc3f50, CServerChannel * pChannel=0x0e0bc540, IRpcStubBuffer * pStub=0x0e17f408, void * pStubBuffer=0x0d7820e0, void * pIPIDEntry=0x0d8e8d98, tagIPIDEntry * pLocalb=0x0d782080, WireLocalThis *) Line 1182  C++
combase.dll!ComInvokeWithLockAndIPID(ServerCall * pServerCall=0x0dcc3f50, tagIPIDEntry * pIPIDEntry=0x0d8e8d98, bool * pbCallerResponsibleForRequestMessageCleanup=0x04c5dc3f) Line 2290    C++
[Inline Frame] combase.dll!ComInvoke(ServerCall *) Line 1803    C++
[Inline Frame] combase.dll!ThreadDispatch(ServerCall *) Line 416    C++
combase.dll!ThreadWndProc(HWND__ * window=0x000707d2, unsigned int message=1024, unsigned int wparam=47806, long params=231489368) Line 744 C++
user32.dll!__InternalCallWinProc@20()   Unknown
user32.dll!UserCallWinProcCheckWow()    Unknown
user32.dll!DispatchMessageWorker()  Unknown
user32.dll!_DispatchMessageW@4()    Unknown
[Inline Frame] combase.dll!CCliModalLoop::MyDispatchMessage(tagMSG *) Line 3057 C++
combase.dll!CCliModalLoop::PeekRPCAndDDEMessage() Line 2693 C++
combase.dll!CCliModalLoop::FindMessage(unsigned long dwStatus=524296) Line 2764 C++
combase.dll!CCliModalLoop::HandleWakeForMsg() Line 2379 C++
combase.dll!CCliModalLoop::BlockFn(void * * ahEvent=0x04c5dfc0, unsigned long cEvents=1, unsigned long * lpdwSignaled=0x04c5dfa8) Line 2316 C++
combase.dll!ModalLoop(CSyncClientCall * pClientCall=0x0d74fc40) Line 166    C++
combase.dll!ClassicSTAThreadDispatchCrossApartmentCall(tagRPCOLEMESSAGE * pMessage=0x04c5e408, OXIDEntry * pOXIDEntry=0x0b87b5c0, CSyncClientCall * pClientCall=0x0d74fc40) Line 321    C++
[Inline Frame] combase.dll!CSyncClientCall::SwitchAptAndDispatchCall(tagRPCOLEMESSAGE * pMessage=0x04c5e408) Line 5696  C++
combase.dll!CSyncClientCall::SendReceive2(tagRPCOLEMESSAGE * pMessage=0x04c5e408, unsigned long * pstatus=0x04c5e3e4) Line 5377 C++
[Inline Frame] combase.dll!SyncClientCallRetryContext::SendReceiveWithRetry(tagRPCOLEMESSAGE *) Line 1617   C++
[Inline Frame] combase.dll!CSyncClientCall::SendReceiveInRetryContext(SyncClientCallRetryContext *) Line 567    C++
combase.dll!ClassicSTAThreadSendReceive(CSyncClientCall * pClientCall=0x0d74fc40, tagRPCOLEMESSAGE * pMsg=0x04c5e408, unsigned long * pulStatus=0x04c5e3e4) Line 549    C++
combase.dll!CSyncClientCall::SendReceive(tagRPCOLEMESSAGE * pMessage=0x04c5e408, unsigned long * pulStatus=0x04c5e3e4) Line 778 C++
[Inline Frame] combase.dll!CClientChannel::SendReceive(tagRPCOLEMESSAGE *) Line 653 C++
combase.dll!NdrExtpProxySendReceive(void * pThis=0x0e0703ec, _MIDL_STUB_MESSAGE * pStubMsg=0x04c5e4e8) Line 1998    C++
rpcrt4.dll!NdrClientCall2() Unknown
combase.dll!ObjectStublessClient(void * ParamAddress=0x04c5e910, long Method=5) Line 227    C++
combase.dll!_ObjectStubless@0() Line 171    Unknown
cmSC24.dll!clsEventSink::Connect(IUnknown * pUnknown=0x0e238d94, const String & sObject={...}, const String & sPrefix={...}, unsigned int * pnErrArg=0x04c5efa0, tagEXCEPINFO * pExepInfo=0x04c5efa4) Line 313  C++
cmSC24.dll!Connect(IUnknown * pUnknown=0x0e238d94, const String & sObject={...}, const String & sPrefix={...}, unsigned int * pnErrArg=0x04c5efa0, tagEXCEPINFO * pExepInfo=0x04c5efa4, clsScriptingHost * pHost=0x0e2f1fe8) Line 462   C++

我将其解释为 combase 尝试设置默认编组,并且在 1903 更新中某处失败。所以我的问题是,为什么它会失败,当我全部 Advise() 时,我的班级需要提供什么?

还是服务器(可连接对象)是在 STA 主线程中创建的,并且必须以某种方式进行更改以支持编组到调用 Advise() 的新线程的事件接收器?

在以前的版本中发现几乎相同的堆栈,但它成功了。

4

1 回答 1

0

啊,好吧 - 在对话框对象中使用 VS 2019 和 _MERGE_PROXYSTUB(以及一些调整)就可以了……标准代理在这里可能是错误的,所以它需要自己提供?什么鬼,我很高兴它有效。

@Raymond:感谢您的回答-这是您引导我的正确轨道!

于 2019-05-14T10:12:27.690 回答