Calling my COM method from C# results in a null st

2019-09-17 11:08发布

问题:

Here is my C# code:

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

Here is my 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, [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;
    };
};

Here is my implementation:

STDMETHODIMP CCrappyCOMService::TestCrap(INT errorCode, BSTR errorMessage, CrapStructure *crapStructure) {
    memset(crapStructure, 0, sizeof(CrapStructure));
    crapStructure->ErrorCode = errorCode;
    crapStructure->ErrorMessage = errorMessage;
    return -1;
}

The Problem: When I return -1 in the above implementation of the TestCrap method, this results in an exception in the C# world. When this happens, crapStructure.ErrorCode is set to 0 and crapStructure.ErrorMessage is null, despite clearly being set to a value of 1337 and, "This is bananas," respectively.

The Question: How can I see the values of crapStructure.ErrorCode and crapStructure.ErrorMessage when TestCrap returns -1? I have verified that similar code works perfectly fine from C++ or if P/Invoking directly from C# instead of using a COM reference over C#.

Furthermore: If I return S_OK (otherwise known as 0) in the above implementation, then I get back 1337 and, "This is bananas," which is what I would expect/want to see even when HRESULT is not 0.

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