你不能,这似乎是设计使然。详细信息如下,但简而言之,您有三个选择:
- 不返回任何消息和一个 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” 。