获取从C#调用的COM方法的错误消息

时间:2017-07-20 02:06:15

标签: c# c++ .net com atl

这是我的IDL:

[
    object,
    uuid(61B0BFF7-E9DF-4D7E-AFE6-49CC67245257),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface ICrappyCOMService : IDispatch {
    typedef
    [
        uuid(C65F8DE6-EDEF-479C-BD3B-17EC3F9E4A3E),
        version(1.0)
    ]
    struct CrapStructure {
        INT ErrorCode;
        BSTR ErrorMessage;
    } CrapStructure;
    [id(1)] HRESULT TestCrap([in] INT errorCode, [in] BSTR errorMessage, [in, out] CrapStructure *crapStructure);
};
[
    uuid(763B8CA0-16DD-48C8-BB31-3ECD9B9DE441),
    version(1.0),
]
library CrappyCOMLib
{
    importlib("stdole2.tlb");
    [
        uuid(F7375DA4-2C1E-400D-88F3-FF816BB21177)      
    ]
    coclass CrappyCOMService
    {
        [default] interface ICrappyCOMService;
    };
};

这是我的C ++实现:

STDMETHODIMP CCrappyCOMService::InterfaceSupportsErrorInfo(REFIID riid)
{
    static const IID* const arr[] = {
        &IID_ICrappyCOMService
    };
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
        if (InlineIsEqualGUID(*arr[i], riid))
            return S_OK;
    }
    return S_FALSE;
}

STDMETHODIMP CCrappyCOMService::TestCrap(INT errorCode, BSTR errorMessage, CrapStructure *crapStructure) {
    memset(crapStructure, 0, sizeof(CrapStructure));
    crapStructure->ErrorCode = errorCode;
    crapStructure->ErrorMessage = errorMessage;
    ICreateErrorInfo* pCreateErrorInfo;
    CreateErrorInfo(&pCreateErrorInfo);
    pCreateErrorInfo->AddRef();
    pCreateErrorInfo->SetDescription(errorMessage);
    pCreateErrorInfo->SetGUID(IID_ICrappyCOMService);
    pCreateErrorInfo->SetSource(L"CCrappyCOMService::TestCrap");
    IErrorInfo* pErrorInfo;
    pCreateErrorInfo->QueryInterface(IID_IErrorInfo, (void**)&pErrorInfo);
    pErrorInfo->AddRef();
    SetErrorInfo(errorCode, pErrorInfo);
    pErrorInfo->Release();
    pCreateErrorInfo->Release();
    return E_FAIL;
}

以下是调用TestCrap方法的C#代码:

static void Main(string[] args)
{
    var service = new CrappyCOMService();
    var crapStructure = new CrapStructure();
    try
    {
        service.TestCrap(1337, "This is bananas.", ref crapStructure);
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.ToString());
    }
    Console.WriteLine(crapStructure.ErrorCode);
    Console.WriteLine(crapStructure.ErrorMessage);
}

我似乎无法弄清楚如何回读我传递给IErrorInfo的错误消息。我在这里错过了什么吗?我在this guide之后实施了ISupportErrorInfo,并在Wikipedia上说:

  

在.NET Framework中,HRESULT / IErrorInfo错误代码已翻译   从本机代码转换为托管代码时转换为CLR异常;   和CLR异常转换为HRESULT / IErrorInfo错误代码   从托管转换为本机COM代码时。

如何正确设置并取回错误消息?

当前的异常消息是

  

错误HRESULT E_FAIL已从调用COM组件返回。

...但我希望它能够返回这是香蕉。

1 个答案:

答案 0 :(得分:1)

您应始终在代码中进行适当的错误检查。这个电话:

SetErrorInfo(errorCode, pErrorInfo);

返回E_INVALIDARG,因为第一个参数必须official documentation为0。替换为:

SetErrorInfo(0, pErrorInfo);

它会起作用。