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

时间:2013-08-21 13:18:21

标签: c# 32bit-64bit dllimport urlmon

我正在创建一个在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

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

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

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

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

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

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

IisAllow32BitApplication

为什么?

它不应该加载我们现在所在的64位系统的dll urlmon.dll吗?

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

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

任何想法/经验?

用于测试的操作系统

桌面:

  1. Windows 8 x64 - 正常工作
  2. Windows 7 x64 - 正常工作
  3. Windows Server 2008 Standard R2 x64 - 正常工作
  4. Windows Server 2008 Standard x86 - 正常工作
  5. Windows Server 2003 Standard x86 - 正常工作
  6. Windows XP Professional SP3 - 正常工作
  7. 网络:

    1. Windows 8 x64 - 找到第一个错误,仅适用于启用32位应用程序
    2. Windows Server 2008 Standard R2 x64 - 错误已确认,仅适用于启用32位应用程序
    3. Windows Server 2008 Standard x86 - 正常工作
    4. 编辑2(问题已解决)

      Noseratio解决:

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

      我知道System.UInt32导致完整的64位网络应用程序出现问题,但我不知道原因。

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

      提前致谢

1 个答案:

答案 0 :(得分:11)

如果您使用了链接的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