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解决:
ppwzMimeOut
和pBC
的正确参数类型必须是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);
注意ppwzMimeOut
和pBC
参数的类型差异。在前一种情况下,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”?