2

我有一个调用 COM 类的 C# Winforms 应用程序。使用 Visual Studio 进行调试时,它会进入 c++ 代码并返回 S_OK 但是当函数返回时,Visual Studio 挂起并且应用程序崩溃。我必须结束 VS 进程上的进程才能停止程序运行。如果我在 Visual Studio 之外运行应用程序,应用程序就会崩溃。

一切正常,我不知道我可能做了什么导致这个问题。

任何帮助表示赞赏。谢谢

Sj

这是接口定义

typedef struct
{
    long    ExpiryData
    BSTR    IssuedBy;
} LicenceData;

[
    object,
    uuid (5A734F95-EABE-440B-8B7E-0F73538A24AC), 
    pointer_default(unique),
    helpstring("ILicenceReader Interface"),
]
interface ILicenceReader : IDispatch
{
    HRESULT ReadLicenceFile ([in, out]LicenceData* plicenceData, LPCTSTR filePath);
};

[
    uuid(C2833A21-6586-4648-ABC8-D42BC3225699)      
]
coclass LicenceReader
{
    [default] interface ILicenceReader;
};

我已经引用了 COM dll 并允许 VS 生成 Interop 和 c# 应用程序中的用法:

LicenceData data = new LicenceData();

ILicenceReader reader = new LicenceReader();

reader.ReadLicenceFile(ref data, filePath);

谢谢你的帮助。

4

1 回答 1

0

我敢打赌,COM 子系统正试图解组分配在堆栈上的 BSTR,或者可能使用堆栈上的智能指针分配。

BSTR 必须使用 SysAllocString 分配。这个结果可以按原样返回,因为它不在堆栈上,并且没有任何东西会尝试错误地释放它。

如果您使用智能指针 BSTR 类,例如 CComBSTR 或 _bstr_t,则需要通过 Detach 设置 IssuedBy 成员。CComBSTR::Detach() 将返回指向 BSTR 的指针,并且当 CComBSTR 的本地实例超出范围时不会尝试释放它。

plicenceData->IssuedBy = CComBSTR("Some Dude").Detach();

另一种可能性是您尝试在 COM 类中执行 plicenceData = new plicenceData 之类的操作,覆盖传入的实例。那是行不通的。

最后,COM 函数在完成并返回后失败的唯一原因几乎是由于编组问题。它是您的 C# 代码和被调用的 C++ 之间的层,它试图跨单元转换数据并可能跨进程边界。您需要确保严格遵守 COM 规则,以允许编组完成其工作。

所以,仔细检查你所有的指针。它们是在堆栈上还是在堆上?他们需要在堆上。是否所有 BSTR 都分配得当?使用智能 BSTR 类通常会有很大帮助,但请记住,您不能返回原始成员。按照预期使用这些类。

于 2012-05-23T00:11:39.057 回答