c# - COM接口(interface)修改突然开始导致异常

标签 c# c++ com visual-studio-2012

几年前,我继承了一个 C# 应用程序,它使用在非托管 C++ DLL 中定义的 COM 对象。从那以后我一直在成功地调整对象接口(interface),但是在(可能不相关的)VS2012 升级之后,函数签名添加和更改突然受到随机异常的惩罚,例如 ExecutionEngineException 和 SEHException。

我的理解是该应用程序使用免注册 COM。没有 DLLRegisterServer 实现,我在注册表中也没有看到接口(interface) guids 的提及,只有 C# 中的一个...

[ComImport,
Guid("C2427CB1-D6AE-49e8-B266-114F981C3353"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
SuppressUnmanagedCodeSecurity()]
public interface IDC
{

还有一个在 C++ 头文件中。

interface __declspec(uuid("C2427CB1-D6AE-49e8-B266-114F981C3353"))
IDC : IUnknown
{

可以肯定的是,我决定将一个新的 guid 交换到这两个地方,并发现它完全阻止了 C# 识别类:

System.InvalidCastException

Unable to cast COM object of type 'System.__ComObject' to interface type 'Apx.IDC'.
This operation failed because the QueryInterface call on the COM component for the
interface with IID '{the new guid}' failed due to the following error:
No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

(上述错误显然通常是由混合公寓状态引起的,但交换 guid 不会导致这种情况)。所以我推断一定有额外的相关细节某处与我的更改相冲突。但是那个地方可能在哪里?感谢阅读...

编辑:

一个异常(exception)的例子是......

First-chance exception at 0x000007feec748be4 (clr.dll) in Apex.exe: 0xC0000005:
Access violation reading location 0xffffffffffffffff.
The Common Language Runtime cannot stop at this exception. Common causes include:
incorrect COM interop marshalling, and memory corruption. To investigate further,
using native-only debugging.

An unhandled exception of type 'System.ExecutionEngineException' occurred in Apex.exe

对于

[PreserveSig] [return: MarshalAs(UnmanagedType.I1)]
bool LoadDisplayList(IntPtr fileHandle, IntPtr pDisplayList,
UInt16 version, IntPtr pComparison);

virtual bool __stdcall LoadDisplayList(HANDLE fileHandle, class CDisplayList * pDisplayList,
WORD version, CDisplayList * pComparison) = 0;

以堆栈跟踪结束

[Native to Managed Transition]  
Apex.Graphics64.dll!CDisplayList::LoadRenderRecs(void * f=0x000000000000056c, CDisplayList * pComparison=0x0000000023ad2cf0)  Line 1772 C++
Apex.Graphics64.dll!CDisplayList::Load(void * f=0x000000000000056c, unsigned short version=0x0002, CDisplayList * pComparison=0x0000000023ad2cf0)  Line 1845 + 0x26 bytes   C++
Apex.Graphics64.dll!CBaseDC::LoadDisplayList(void * f=0x000000000000056c, CDisplayList * pList=0x0000000023ad2cf0, unsigned short version=0x0002, CDisplayList * pComparison=0x0000000023ad2cf0)  Line 1896 + 0x33 bytes    C++
[Managed to Native Transition]  
Apex.exe!Apex.DDC.LoadDisplayList(System.IO.FileStream file = {System.IO.FileStream}, Apex.DisplayList displayList = {Apex.DisplayList}, ushort version = 0x0002, Apex.DisplayList comparison = null) Line 1124 + 0xaf bytes    C#
Apex.exe!Apex.DisplayList.Load(System.IO.FileStream f = {System.IO.FileStream}, ushort loadVersion = 0x0002, Apex.INode stubsRoot = {Apex.ViewPort3D}, Apex.DisplayList comparison = null) Line 166 + 0x53 bytes    C#

确切的崩溃点有所不同 - 这里它实际上设法进入了 LoadDisplayList(),这比平时要好。由于崩溃表明堆损坏,我尝试将函数的签名剥离为无参数的 void 返回,将其内容减少为跟踪,并在对象创建后立即调用它 - 仍然会发生崩溃。如果我将它移到定义的顶部,相同的函数不会崩溃,在这种情况下,一些其他接口(interface)函数会崩溃,这让我认为它更有可能是 COM 问题,而不是算法级内存损坏。

最佳答案

我想我已经解决了这个问题。一旦我能够稍微进入 DLL,一个弹出窗口说源与可执行文件不匹配,这让我调查了另一个长期存在但以前没有问题的怪癖,即 DLL 的链接器/通用/输出文件不在项目的通用/输出目录(警告 MSB8012)。清除此异常后,我能够成功更改 guid,因此 VS2012 使用这些设置似乎与旧版本略有不同。道德……不要让警告四处流传。

关于c# - COM接口(interface)修改突然开始导致异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15573407/

相关文章:

.net - COM+ 长时间运行的方法导致其他方法阻塞/挂起

c# - 测试 com dll 是否使用其路径注册

c# - 以编程方式构建表以导出到 JSON 或从 JSON 导入?

c# - 使用 RemoveRange 删除与内存对象匹配的项目

c++ - 蒂姆·斯威尼在想什么? (这个 C++ 解析器是如何工作的?)

c++ - 将 QLineEdit 对象的内容保存到字符串变量中 (C++)

javascript - 如何将 Javascript 中的返回值传递给 Controller

c# - 用 HTML5 播放 wav

c++ - Typedef 映射作为函数的返回类型会引发编译器错误

c++ - 创建实现特定接口(interface)的 ATL COM 对象