几年前,我继承了一个使用非托管C ++ DLL中定义的COM对象的C#应用程序。我已经成功地调整了对象接口于是乎,但以下(可能不相关)VS2012升级,函数签名添加和更改突然被随机例外,如ExecutionEngineException和SEHException处罚。
我的理解是该应用程序使用免注册COM。没有DLLRegisterServer实现,我没有看到注册表中的接口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)).
(上述错误显然通常是由混合公寓状态引起的,但交换指南不会导致这种情况)。因此,我推断必须有与我的更改冲突的其他相关详细信息某处。但那可能在某个地方?谢谢你的阅读...
编辑:
示例例外是......
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返回,将其内容减少到跟踪,并在对象创建后立即调用它 - 仍然会发生崩溃。如果我将它移动到定义的顶部,相同的函数不会崩溃,在这种情况下,其他一些接口函数崩溃了,这使我认为它更可能是一个COM问题,而不是算法级别的内存损坏。
答案 0 :(得分:1)
我想我已经解决了这个问题。一旦我能够进入DLL一点,一个弹出窗口说源与可执行文件不匹配导致我调查另一个长期但以前没有问题的怪癖,DLL的链接器/通用/输出文件不在项目的内部通用/输出目录(警告MSB8012)。清理完这个异常之后我就能成功更改guid,所以看起来VS2012使用这些设置与旧版本略有不同。道德......不要让警告徘徊。