如何从ATL返回正向错误代码到VB6?

5
我已经查看了此答案:如何从 ATL ActiveX 控件向 VB6 返回错误字符串和错误代码?
我可以返回自定义的负误差代码,即设置了严重性位,并生成自定义错误消息。但是,我希望能够生成 VB6 将呈现为正 # 的代码,以便用户更容易使用。我相信这是可以做到的,因为 Microsoft 的 DAO 3.6 DLL 能够实现。例如,如果表不存在,则返回 Err.Number=3078 和 Err.Description "The Microsoft Jet database..."。
请注意,我已经实现了 ISupportErrorInfo 等用于错误报告的接口。
2个回答

5

稍作注释一下Mark的回答。他正确地使用了FACILITY_CONTROL。此外,您必须确保错误代码大于512,以避免与VB6运行时错误代码发生冲突。因此,请使用以下代码:

HRESULT MakeVB6Error(UINT errCode) {
    assert(errCode > 0 && errCode < 65536 - 513);
    return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_CONTROL, errCode + 513);
}

以下是关于如何从 C# 中进行相同操作的类似答案(适用于通过谷歌到达此处的人):在 C# 中通过 COM 互操作引发正面 VB 风格的错误代码 - Deanna

4

VB进行了许多HRESULT值到Err.Number值的映射。例如,如果HRESULT为0x8007002,则VB将其拆分使用COM标准如下:

Bit 31 - Severity (set to 1 in all errors)
Bit 30 - Reserved
Bit 29 - Customer Bit
Bit 28 - Reserved
Bit 27 
  - 16   Facility code
Bit 15 
  -  0   Error code

实际上,最高的四位始终为8。Facility会变化,告诉你这是什么类型的错误。在这种情况下,facility代码是0x007(FACILITY_WIN32),这意味着这是一个标准的Win32错误。较低的两个字节表示实际错误。查看winerror.h,此错误为2 - ERROR_FILE_NOT_FOUND。VB足够聪明,可以将此错误映射到标准VB错误53“文件未找到”。
在VB文档中,我们总是被鼓励在从VB组件引发错误时添加常量vbObjectError到我们的错误编号中。这几乎相当于对您的错误编号(假设它小于等于65535)进行OR运算的32位整数0x80040000。在这种情况下,facility代码为0x4(FACILITY_ITF),表明该错误是从coclass的特定接口引发的。实际上,这只是使我们的错误编号变得更大、更负面和难以理解。
我们真正应该做的是忽略文档并直接引发直接的错误编号。在幕后,VB OR了自己的facility代码-0xA(FACILITY_CONTROL)。但是,任何看到带有该facility代码的HRESULT的VB组件都会自动清除前两个字节,因此我们将看到该数字为正数-而不是负数。
我建议您使用FACILITY_CONTROL作为自己的错误编号。其他COM客户端可能会感到困惑,但VB客户端会将您的错误编号视为正数。
或者,您可以忽略常规的HRESULT机制以返回值。相反,返回HRESULT = S_OK,并在函数末尾使用[retval,out]参数,使其看起来像是一个VB函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接