检查 COM 指针是否存在

Check existence of COM pointer

本文关键字:存在 是否 指针 COM 检查      更新时间:2023-10-16

在 c++ 中,MFC:

我有一个CComPointer:

CComPointer<IMyTask> m_pTask;

我的代码中有很多地方,我调用此 ComPointer 来运行任务的方法。例如:

void method1()
 {
    if (FAILED(hRet = m_pTask->MyFunc1()))
                  .....
 }
void method2()
{
    if (FAILED(hRet = m_pTask->MyFunc2()))
                  .....
}

我尝试解决一个问题,以便在MyTask关闭时恢复。我写了一个方法,recover(),将CoCreate重新运行到MyTask,它实际上解决了这个问题。

我可以看到,如果MyTask死了,我得到的HR失败代码为-2147023174,RPC服务器不可用。但是,com 指针m_pTask具有完整的数据(它不知道任务已死)。

我可以做这样的事情:

void method1()
 {
    if (FAILED(hRet = m_pTask->MyFunc1()))
        if (hRet == -2147023174)
           recover();
                  .....
 }
void method2()
{
    if (FAILED(hRet = m_pTask->MyFunc2()))
        if (hRet == -2147023174)
           recover();
                  .....
}

但是,因为我通过指针对方法有很多调用,所以我想做一些更通用的东西。我希望每次尝试通过 ComPointer 运行方法时,在运行该方法之前,检查任务是否已存在,如果没有 - 运行恢复方法。因为即使任务已死,ComPointer 仍然拥有 CoCreate 时间的所有数据,我不知道该怎么做。

我该怎么做?

由于系统中发生的错误,该任务已死亡,目前我的解决方案不需要找到任务失败的原因,只需恢复它即可。我正在寻找一个通用的解决方案 - 比如 ComPointer 的包装器,但我希望包装器类只检查 MyTask 是否仍然存在,如果是 - 它将返回 ComPointer,如果没有,它将运行恢复。

我该怎么做?

好的,这是一个一般性问题的一般性答案。我不想知道,为什么任务实际上是死的,而指针不是。为任务指针编写一个包装器并改用它。它将看起来像这样:

class CMyTaskWrapper
{
     CComPtr<IMyTask> m_ptr;
     ...
     HRESULT myFunc1()
     {
         HRESULT hRes = m_ptr->myFunc1();
         if(hRes == 0x800706BA)
         {
             recover();
         }
         return hRes;
     }
     ... //here you should list all members of IMyTask
 };

编辑1:添加了一个宏示例(请参阅注释#2)

MYMACRO_0(HRESULT_GETTER, POINTER, FUNCTION) 
HRESULT_GETTER = POINTER->FUNCTION(); 
if(HRESULT_GETTER == 0x800706BA) recover(); 
HRESULT_GETTER = POINTER->FUNCTION() 
MYMACRO_1(HRESULT_GETTER, POINTER, FUNCTION, PARAM1) 
HRESULT_GETTER = POINTER->FUNCTION(PARAM1); 
if(HRESULT_GETTER == 0x800706BA) recover(); 
HRESULT_GETTER = POINTER->FUNCTION(PARAM1)
//here you should add MYMACRO_2 ... MYMACRO_N

您可以通过以下方式使用它:

MYMACRO_0(hRes, m_pTask, MyFunc1);
MYMACRO_1(hRes, m_pTask, MyFunc2, parameter_to_pass);

这可能会有所帮助,这将隐藏函数列表,但尽管如此,使用这样的代码并不是一个好主意。

CComPointer 的实现相当简单。 您可以轻松地剪切和粘贴它以形成您自己的智能指针类的基础。

CComPointer 实现依赖于重写"->"运算符。 这避免了了解接口提供哪些方法的需要。 每个呼叫都会被有效地拦截,然后被转发。

在新的智能指针类中,您可以构建所需的额外功能来实现"->"运算符重写。

进行哪些检查来验证呼叫更难。

我认为 QueryInterface

是一个有效的调用,您可以使用它来检查连接是否处于活动状态 - QueryInterface 保证存在,并且需要调用到真正的实现。

但是,总会存在争用条件 - 检查呼叫和实际呼叫之间的连接可能会失败。

因此,您可能最好只是进行真正的调用,如果失败,请尝试恢复并再次调用 - 这在一个很好的模式中很难做到 - 可能最容易实现的宏参见Forgottn的答案。

听起来你想要一个自定义的DCOM代理,而不是midl和Windows提供的默认逻辑。 这是可能的,但这也是很多工作。 如果需要向使用 COM 创建对象的第三方代码提供自定义行为,这是最佳选择。

当您控制客户端代码时,编写一个实现相同 COM 接口的包装类可能会更简单,并且通过将每个调用转发到远程服务器来实现。

MFC 类向导允许您围绕 com 组件生成包装类。本页介绍了如何操作。

生成包装类后 - 您可以编辑任何方法以在其中实现重试逻辑。您可以对 #import 指令生成的包装类使用相同的方法。