执行自定义 COM 客户端和服务器时访问读写异常

问题描述 投票:0回答:1

这个问题建立在this问题

中链接的代码之上

在我对自定义编组的研究中,我遇到了这篇文章,它为我提供了在没有 Visual Studio 帮助的情况下创建自己的代理/存根所需的所有见解。

这里是完整项目的链接,请按照this问题中完全相同的说明来启动和运行服务器和客户端

那么问题出在哪里?

首先让我告诉你什么不是问题

  1. 代理在客户端创建
  2. 存根在服务器端创建

两端的一切都完全按照计划进行设置,直到随机发生错误。当我说随机时,我是认真的,

  1. 有时您会遇到写访问冲突异常

  2. 其他时候出现执行违规异常

  3. 最后(我认为)你在这里得到另一个例外

我已经调试了一天多了,但仍然无法确定为什么这些代码段总是随机失败,这就是为什么我在这里寻求调试帮助。

如果有人确实设法让此代码工作,那么 Com 客户端应该与 COM 服务器通信,您将在客户端看到类似这样的输出

Click 1
Scroll 10
Key Pressed 5
Key Released 10

基本上,COM 服务器将这些字符串作为字符数组从 STUB 发送到 PROXY,代理最终打印接收到的值。

c++ winapi proxy com stub
1个回答
0
投票

请注意,使用生成的 RPC 代理/存根的标准封送不是 Visual Studio 功能,它由 Windows SDK 提供。 MIDL,.IDL 编译器是一个 SDK 工具,可生成默认的 P/S 文件(.c、.h 等),因此它确实是 Windows 功能。

Visual Studio(通用工具,通常与 ATL 结合使用)只是为您简化了 MIDL 的调用。

现在,在没有生成的代理/存根的情况下进行标准封送仍然是可能的,但我不会推荐它,除非您有充分的理由这样做。原因包括在来回传输参数时进行非常具体的优化,您知道您可以使用这些优化,但您知道系统不能。例如,生成的 RPC 代码将使用大块内存传输特定类型的参数(如字符串或字节数组),并且您可以以不同的方式传输(如特定上下文内部某些内容的共享句柄)。

它现在可以在提到的存储库中运行,所以让我们回到一些必须修复的故障:

  • 您遇到的第一个问题是必须使用传递给
    IPSFactoryBuffer::CreateProxy方法
    pUnkOuter参数,因此至少
    AddRef
    ,完成后
    Release
  • 还必须将
    pUnkOuter
    委托给任何其他接口的所有
    QueryInterface
    调用,而不是
    IRpcProxyBuffer
    并且 不是 代理接口:
    IMouse
    IKeyboard
    等。(这些必须当然由代理实现者实现)
  • 如果 Connect 调用紧随其后的是 Disconnect 调用(代理或存根),则意味着代码中某处存在一些引用计数问题,导致系统提供的代理管理器认为它必须终止代理/有问题的存根。如果不使用
    pUnkOuter
    ,这就是代理端发生的情况。
  • 在代理端,当调用 IRpcChannelBuffer::GetBuffer 时,RPCOLEMESSAGE 结构的 iMethod 字段 必须 已设置为方法的 vtable 索引(必须 >= 3,因为 vtable 始终至少具有3 个 IUnknown 方法(QueryInterface、AddRef、Release)。如果在
    iMethod
    调用之后设置
    GetBuffer
    ,则永远不会到达存根的 IRpcStubBuffer::Invoke,并且代理将在
    SendReceive 方法的 
    RPC_E_INVALID_HEADER
     out 参数中收到 
    pStatus 错误 (0x80010111) 。请注意,“Inside COM+”一书在这里是错误的(或者也许事情已经发生了变化,但我对此表示怀疑)。

其他备注:

  • 这取决于上下文,但您应该使
    AddRef
    Release
    实现线程安全,例如使用 InterlockedIncrementInterlockedDecrement 而不是
    ++
    --
    运算符。好的练习,让每个人都更容易。
  • IsIIDSupported 方法 实现应该
    AddRef
    将接口返回给调用者(与 COM 一样)。
© www.soinside.com 2019 - 2024. All rights reserved.