5

我正在尝试使用CComCoClass::Error向 VB6 返回详细错误,但似乎我只能返回错误代码/或/消息 - 但不能同时返回两者。

return Error(_T("Not connected"), __uuidof(IMyInterface), HRESULT_FROM_WIN32(ERROR_CONNECTION_INVALID));

在 VB6 端的 Err.Description 中导致通用的“方法 'Request' of object 'IMyInterface' failed”错误消息(但 Err.Number 中的 ERROR_CONNECTION_INVALID),而

return Error(_T("Not connected"));

导致相应的错误消息,但 Err.Number 中的通用错误代码。我怎样才能两全其美?

4

4 回答 4

5

你不能,这似乎是设计使然。详细信息如下,但简而言之,您有三个选择:

  • 不返回任何消息和一个 VB 友好的 COM 错误,即根据这篇知识库文章VB 运行时所熟知的错误;VB 运行时会将此“COM 错误”转换为 VB 错误加消息。
  • 返回错误信息和 DISP_E_EXCEPTION;VB 运行时将通过此“服务器错误”和您的自定义错误消息。这是您的第二个示例中隐含的情况,有关详细信息,请参见下文。
  • 不返回任何消息和任何其他 COM 错误,即VB 运行时不知道的错误;VB 运行时将求助于原始 HRESULT 加上通用消息“ Method '~' of object '~' failed”。
    • 请注意,此运行时行为也适用,如果您在此处提供错误消息,即您的消息将被忽略!这是您的第一个示例中发生的情况,有关详细信息,请参见下文。

对于手头的任务,它归结为两个选择:

  • 如果您想为 VB 等自动化客户端提供上下文正确的“COM 错误”(您可能应该这样做),您必须省略自定义错误消息。
  • 如果您想为“服务器错误”提供自定义错误消息(即有关自动化服务器中的功能的自定义错误条件 ,您唯一的选择是 DISP_E_EXCEPTION。

细节

VB 运行时似乎只对 COM 错误提供非常有限的处理。这可能是出于特定于 VB 实现方式的历史和/或技术原因,在这里并不特别感兴趣(关键字将是仅 IDispatch 与双接口和 ActiveX 作为 COM 的“子集”)。

虽然我无法为上述行为提出明确的规范,但可以通过挖掘其他来源来确定:

知识库文章justadreamer已经指出

[...] 调用 GetErrorInfo 方法以检索可用的错误信息。然后运行时确定 bstrDescription 是否具有 NULL 以外的值。如果运行时找到 NULL 以外的值,[...],则在此方案中使用原始 HRESULT 值。如果运行时发现 NULL 值,[...] Visual Basic 然后使用 HRESULT 查找相应的 Visual Basic 错误。

这解释了关于您的第一个示例的行为:您确实提供了一条错误消息,因此运行时只是诉诸其通用消息“ Method '~' of object '~' failed”加上您的HRESULT.

一旦您查看(第一个列出的)构造函数的定义,第二个示例的行为也是一致的CComCoClass::Error:它具有未指定参数的默认值,尤其是“hRes = 0”。“备注”部分进一步指出“如果 hRes 为零,则错误的前四个版本返回 DISP_E_EXCEPTION。”。因此,这隐含地触发了“服务器错误”传递行为。

最后,对于类似 VB 的自动化客户端行为的具体 C++ 实现示例,请参见自动化 Microsoft Office 97 和 Microsoft Office 2000中的“错误处理”段落和以下“练习 5” 。

于 2009-07-15T12:15:20.060 回答
0

我现在也在为此苦苦挣扎。到目前为止,我的挖掘表明错误代码实际上是 HRESULT 值。VB6 试图变得聪明并解释 HRESULT,但它所理解的 HRESULT 列表似乎相当有限。对于 VB6 不熟悉的 HRESULT,它只是将 HRESULT 放入 Err.Number 属性中,并希望开发人员足够聪明,弄清楚如何处理它。

我最接近返回错误号的方法是使用 MAKE_SCODE 生成一个 HRESULT,并将 HRESULT 的代码字段设置为我想要的,设置严重性标志以及我希望是正确的工具。

与 CreateErrorInfo 和 SetErrorInfo 一起在 VB6 中为我提供错误代码和错误描述。这让我们回到了 VB6,试图在有限的错误列表中变得聪明。

于 2009-07-09T00:06:46.183 回答
0

查看这篇文章http://support.microsoft.com/kb/827994。因此,您的对象必须实现返回 S_OK 的方法 ISupportsErrorInfo::InterfaceSupportsErrorInfo()。然后在返回之前,您必须调用 SetErrorInfo,并使用指向实现 IErrorInfo::GetDescription() 的 COM 对象的指针。这里有一个例子:http: //msdn.microsoft.com/en-us/library/ms221409.aspx

如果您在返回之前设置了SetErrorInfo,VB 将查询您传递给SetErrorInfo 的对象指针的GetDescription 方法。

我对您正在使用的属性代码并不太了解——我更愿意使用更原始的 COM 来测试它,这肯定总是有很多样板代码——但至少它可以工作,然后你可以使用复杂的包装器来代替它。

于 2009-07-14T21:15:46.620 回答
0

从 ISupportErrorInfoImpl 派生实现 COM 公开接口的类,调用 SetErrorInfo 设置错误的详细说明(如果有)。不要忘记将 ISupportErrorInfo 包含到您班级的 COM_MAP 中。

于 2009-07-02T13:05:29.207 回答