11

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

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

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

使用 .NET,如何根据文件签名而不是扩展名找到文件的 mime 类型

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

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

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

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

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

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

IisAllow32BitApplication

为什么?

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

这是一个大问题,因为该FindMimeFromData方法可以在这个库的任何地方调用:

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

有什么想法/经验吗?

用于测试的操作系统

桌面:

  1. Windows 8 x64 -工作
  2. Windows 7 x64 -工作
  3. Windows Server 2008 Standard R2 x64 -有效
  4. Windows Server 2008 标准 x86 -有效
  5. Windows Server 2003 标准 x86 -有效
  6. Windows XP Professional SP3 -有效

网站:

  1. Windows 8 x64 -发现第一个错误,仅适用于启用 32 位应用程序
  2. Windows Server 2008 Standard R2 x64 -已确认错误,仅适用于启用 32 位应用程序
  3. Windows Server 2008 标准 x86 -有效

编辑2(问题已解决)

Noseratio解决:

正确的参数类型ppwzMimeOut并且pBC必须是System.IntPtr代替System.UInt32.

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

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

提前致谢

4

1 回答 1

17

如果您使用链接的答案中的 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.

参考这个看起来是正确的实现。

于 2013-09-01T00:59:59.970 回答