urlmon.dll FindMimeFromData() 在 64 位桌面/控制台上完美运行,但在 ASP.NET 上生成错误

Posted

技术标签:

【中文标题】urlmon.dll FindMimeFromData() 在 64 位桌面/控制台上完美运行,但在 ASP.NET 上生成错误【英文标题】:urlmon.dll FindMimeFromData() works perfectly on 64bit desktop/console but generates errors on ASP.NET 【发布时间】:2013-08-23 21:23:23 【问题描述】:

我正在创建一个实用程序库,可在 Web 环境中的桌面环境中使用。

它包含几个我认为在我的应用程序中经常重复使用的功能,包括通过文件内容(而不是扩展名)获取文件的 mime 类型的实用程序。

我要检查的文件是最常见的(jpg、png、pdf、txt),所以我选择使用外部方法FindMimeFromData(上面的链接)

Using .NET, how can you find the mime type of a file based on the file signature not the extension

该方法效果很好,除了 JPG (image/pjpg) 和 PNG (image/x-png) 这两个不正确的 mime 类型,通过在 return 语句之前进行检查很容易解决。

该库是为 AnyCPU 平台编译的,因为它必须安装在 32 位和 64 位的服务器/客户端上。

在桌面环境中进行测试时,所有为 x86 和 x64 编译的应用程序都可以正常工作。

在测试 ASP.NET 应用程序(一个带有用于测试的 http 处理程序的空站点)时发生 HRESULT 类型的错误,并且调试器告诉我它无法提供更多信息。

经过一些测试配置,包括将池的身份更改为本地系统(没有结果),我发现了问题:

池应该允许 32 位应用程序(见上图)。

为什么?

应该不会加载我们现在所在的64位系统的dllurlmon.dll吧?

这是个大问题,因为FindMimeFromData 方法可以被任何地方调用到这个库中:

结果是另一个实用程序方法调用此方法可能会引发此异常,并且难以通过调试来跟踪问题。

有什么想法/经验吗?

用于测试的操作系统

桌面:

    Windows 8 x64 - 工作 Windows 7 x64 - 工作 Windows Server 2008 Standard R2 x64 - 工作 Windows Server 2008 Standard x86 - 工作 Windows Server 2003 Standard x86 - 工作 Windows XP Professional SP3 - 工作

网页:

    Windows 8 x64 - 发现第一个错误,仅适用于启用 32 位应用程序 Windows Server 2008 Standard R2 x64 - 已确认错误,仅适用于启用 32 位应用程序 Windows Server 2008 Standard x86 - 工作

编辑 2(问题已解决)

由Noseratio解决:

ppwzMimeOutpBC的正确参数类型必须是System.IntPtr而不是System.UInt32

我知道System.UInt32 会导致完整的 64 位网络应用出现问题,但我不知道为什么。

如果有人知道这些问题的原因,可以在评论中更好地解释吗?

提前致谢

【问题讨论】:

这就是为什么有一个URLMon.dll 的后备方法就像this 一样好。或者在你的情况下完全放弃 urlmon 以支持 Winista。 【参考方案1】:

如果您使用链接的 answer 中的 pinvoke 签名,它的定义如下:

[DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
private extern static System.UInt32 FindMimeFromData(
    System.UInt32 pBC,
    [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
    [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
    System.UInt32 cbSize,
    [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
    System.UInt32 dwMimeFlags,
    out System.UInt32 ppwzMimeOut,
    System.UInt32 dwReserverd
);

我宁愿使用pinvoke.net的定义:

[DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
static extern int FindMimeFromData(IntPtr pBC,
    [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I1, SizeParamIndex=3)] 
    byte[] pBuffer,
    int cbSize,
    [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
    int dwMimeFlags,
    out IntPtr ppwzMimeOut,
    int dwReserved);

注意ppwzMimeOutpBC 参数的类型差异。在前一种情况下,System.UInt32 不是 64 位平台下 64 位指针的正确类型。对于pBC,这可能不是问题(只要它为NULL),但对于ppwzMimeOut 很重要。

请参阅this implementation,这似乎是正确的。

【讨论】:

嘿伙计... 更改参数 pBC 和 ppwzMimeOut 的类型后,现在它无处不在!非常感谢! 没问题,很高兴它有帮助:] 顺便说一句,不要忘记在ppwzMimeOut 上致电Marshal.FreeCoTaskMem(如图here),否则会泄漏。

以上是关于urlmon.dll FindMimeFromData() 在 64 位桌面/控制台上完美运行,但在 ASP.NET 上生成错误的主要内容,如果未能解决你的问题,请参考以下文章

在 MIME 类型检查期间,应用程序池因 URLMoniker urlmon.dll 崩溃

在 MIME 类型检查期间,应用程序池因 URLMoniker urlmon.dll 崩溃

为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?

为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?

为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?

为啥 Urlmon.dll 中的 FindMimeFromData 函数为许多文件类型返回 MIME 类型“application/octet-stream”?