无法捕获通过PInvoke调用的C DLL引起的异常

7
我正在编写一个使用最新的MediaInfoLib Dll的C# .NET 3.5程序。
似乎对于某些文件会引发异常。
我想捕获这些异常并确保我的程序继续运行,
但由于某种原因,我无法使用简单的try/catch语句来捕获它。
PInvoke方法:
    [DllImport("MediaInfo.dll")]
    private static extern IntPtr MediaInfo_New();
    [DllImport("MediaInfo.dll")]
    private static extern IntPtr MediaInfo_Open(IntPtr Handle,MarshalAs(UnmanagedType.LPWStr)] string FileName);

使用方法:

    Handle = MediaInfo_New();
    try{
        MediaInfo_Open(Handle, FileName)
    } catch { } 

调用MediaInfo_Open(Handle, FileName)可能会导致异常。
我程序没有使用try/catch语句来捕获错误,而是退出并导致“vshost32-clr2.exe”崩溃。(它也会在发布版本中崩溃,并且未附加调试器)
在搜索网络后,我发现有人建议检查“启用非托管代码调试”,但这只导致我的程序退出而不是vshost32-clr2.exe崩溃。
你有什么办法可以捕获异常吗?

您是否在x64操作系统上运行此程序? - ahawker
1
根据文档,MediaInfo_Open函数不返回任何指针,而是返回size_t。当一切正常时,它实际上返回1,当发生错误时返回0,因此这就是如何进行错误处理的答案。 (由于这似乎是最初为C ++库设计的,您可能更喜欢C ++ / CLI而不是PInvoke,至少我会这样做。) - DaVinci
Win7 x64,以32位构建并使用32位的MediaInfoLib。@rene 我刚刚精简了我在这里发布的代码,实际上我正在使用包装器。 - Arokh
@Arokh,你知道如何调用dll吗?我正在使用media info.dll,但是当我在我的测试服务器(64位)部署时,它显示无法加载mediainfo库?有什么想法或解决方法吗? - Usher
2个回答

7

如果非托管的DLL导致崩溃(而不仅仅是返回某种错误代码),那么没有办法捕获它。一旦你超出了.NET运行时的控制范围,完全取决于非托管代码;.NET运行时无能为力。


2
嗯,我其实并不想捕获异常。 我只是不希望我的程序崩溃。这也不可能吗? - Arokh
@Arokh: 我没有使用过那个库,但我肯定可以想象它是可能的!;) 你问的问题(以及未来可能会有其他人问到这个问题)是是否以及如何将错误捕获为异常,答案是“不行”。 - Adam Robinson
我在提问时应该更加谨慎,哈哈。简而言之,如果这个不受管理的库想要使我的程序崩溃,那么我就没有办法阻止它吗? - Arokh
1
@Arokh:很不幸,不行;非托管库可以做任何Windows允许它们做的事情,包括在熊熊烈火中炸毁您的应用程序。 - Adam Robinson
我尝试使用属性[HandleProcessCorruptedStateExceptions]注释调用本地方法的方法,该属性处理像AccessViolationException这样的CSE,并且它可以正常工作,但我正在寻找一种解决方案,以捕获和记录所有异常(可能随时从DLL抛出)。 - Lukáš Koten

0

我曾经遇到过类似的问题(特别是与BSTR有关),但希望这可以帮到你。

在从非托管代码内部传回字符串时,.NET存在一个错误(已在4.0中修复)。更多信息

解决方法是更改您的P/Invoke签名以使用IntPtr并自己执行字符串编组。

[DllImport("MediaInfo.dll", EntryPoint = "MediaInfo_Open")]
private static extern IntPtr _MediaInfo_Open(IntPtr handle, IntPtr filename);

internal static extern IntPtr MediaInfo_Open(IntPtr handle, string filename)
{
     IntPtr stringPtr = Marshal.StringToBSTR(filename);
     return _MediaInfo_Open(handle, stringPtr);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接