我正在尝试使用CComCoClass::Error向VB6返回详细错误,但似乎我只能返回错误代码/或/消息 - 但不能同时返回两者。
return Error(_T("Not connected"), __uuidof(IMyInterface), HRESULT_FROM_WIN32(ERROR_CONNECTION_INVALID));
导致VB6端的Err.Description中的对象'IMyInterface'失败的通用“方法'请求'失败”错误消息(但Err.Number中的ERROR_CONNECTION_INVALID),而
return Error(_T("Not connected"));
会产生相应的错误消息,但Err.Number中会出现一般错误代码。我如何才能充分利用这两个世界?
答案 0 :(得分:5)
你不能,这似乎是设计的。详情如下,但简而言之,您有三种选择:
Method '~' of object '~' failed
”。
对于手头的任务,归结为两种选择:
VB运行时似乎只提供有关COM错误的非常有限的处理。这可能是出于VB实现方式的特定历史和/或技术原因,而不是特别感兴趣的(关键字只有IDispatch vs双接口,ActiveX作为COM的'子集')。
虽然我无法针对上述行为制定明确的规范,但可以通过挖掘其他来源来解决这个问题:
来自KB article justadreamer pointed out already:
[...]打电话给 GetErrorInfo方法来检索 可用的错误信息。该 然后运行时确定是否 bstrDescription的值不是 空值。如果运行时找到值 除了NULL,[...],原始HRESULT 值在此方案中使用。如果 运行时发现一个NULL值,[...] 然后Visual Basic使用HRESULT 查找相应的Visual 基本错误。
这解释了有关您的第一个示例的行为:您确实提供了错误消息,因此运行时只需转到其通用消息“Method '~' of object '~' failed
”加上您的HRESULT
。
在查看CComCoClass::Error
的(第一个列出的)构造函数的定义后,第二个示例的行为也是一致的:它具有非指定参数的默认值,尤其是'hRes = 0'。 “备注”部分进一步指出“如果hRes为零,那么Error的前四个版本将返回DISP_E_EXCEPTION。”。因此,这隐含地触发了“服务器错误”传递行为。
最后,对于像自动化客户端行为这样的VB的具体C ++实现示例,请参阅Automating Microsoft Office 97 and Microsoft Office 2000中的段落“错误处理”和以下“练习5”。
答案 1 :(得分:0)
从ISupportErrorInfoImpl派生实现COM暴露接口的类,调用SetErrorInfo以设置错误的详细说明(如果有)。不要忘记将ISupportErrorInfo包含到您的类的COM_MAP中。
答案 2 :(得分:0)
我现在也在努力解决这个问题。到目前为止,我的挖掘表明错误代码实际上是HRESULT值。 VB6试图变得聪明并解释HRESULT,但它似乎有一个相当有限的HRESULT列表。对于VB6不熟悉的HRESULT,它只是将HRESULT放入Err.Number属性中,并希望开发人员足够聪明,可以弄清楚如何处理它。
我最接近返回错误号是使用MAKE_SCODE生成HRESULT,其中HRESULT的代码字段设置为我想要的,严重性标志设置以及我希望是正确的设施。
与CreateErrorInfo和SetErrorInfo一起在VB6中获取错误代码和错误描述。这让我们回到VB6,试图通过有限的错误列表来实现智能化。
答案 3 :(得分:0)
查看这篇文章http://support.microsoft.com/kb/827994。所以你的对象必须实现返回S_OK的方法ISupportsErrorInfo :: InterfaceSupportsErrorInfo()。然后在返回之前,必须使用指向实现IErrorInfo :: GetDescription()的COM对象的指针调用SetErrorInfo。 这里有一个例子: http://msdn.microsoft.com/en-us/library/ms221409.aspx
如果在返回之前有SetErrorInfo,VB将查询传递给SetErrorInfo的对象指针的GetDescription方法。
我对你使用的属性代码并不太深 - 我宁愿使用更多的原始COM测试它,这肯定总是很多样板代码 - 但至少它可以工作,那么你可以使用复杂的包装而不是它