Urlmon.dll FindMimeFromData() отлично работает на 64-битном рабочем столе/консоли, но генерирует ошибки в ASP.NET

Я создаю библиотеку утилит, которые будут использоваться как в среде рабочего стола в веб-среде.

Он содержит несколько функций, которые, как я полагаю, часто повторяются в моих приложениях, включая утилиту, чтобы получить тип mime файла по его содержимому (а не расширение).

Файлы, которые мне нужно проверить, являются наиболее распространенными (jpg, png, pdf, txt), поэтому я решил использовать внешний метод FindMimeFromData (ссылка выше)

Используя .NET, как вы можете найти тип mime файла на основе имени файла, а не расширения

Метод работает хорошо, за исключением двух неправильных типов mime JPG (image/pjpg) и PNG (image/x-png), которые легко решаются путем проверки перед оператором return.

Библиотека скомпилирована для платформы AnyCPU, поскольку она должна быть установлена ​​на серверах/клиентах как на 32, так и на 64 бит.

Во время тестирования среды рабочего стола все работает исправно для обоих приложений, скомпилированных для x86 и x64.

во время тестирования приложения ASP.NET(пустой сайт с обработчиком HTTP для теста) возникает ошибка типа HRESULT, и отладчик сообщает мне, что он не может предоставить дополнительную информацию.

После нескольких тестовых конфигураций, включая изменение идентификатора пула в локальной системе (без результата), я определил проблему:

пул должен разрешить 32-разрядные приложения (см. изображение выше).

IisAllow32BitApplication

Почему?

Не следует загружать dll urlmon.dll из 64-битной системы, где мы сейчас?

Это большая проблема, потому что метод FindMimeFromData может быть вызван всюду в эту библиотеку:

результат состоит в том, что вызов этого метода другим методом утилиты может вызвать это исключение и затруднить отслеживание проблемы также путем отладки.

Любые идеи/опыт?

Операционные системы, используемые для тестирования

Desktop:

  • Windows 8 x64 - работает
  • Windows 7 x64 - работает
  • Windows Server 2008 Standard R2 x64 - работает
  • Стандарт Windows Server 2008 x86 - работает
  • Стандарт Windows Server 2003 x86 - работает
  • Windows XP Professional SP3 - работает

Web:

  • Windows 8 x64 - обнаружена первая ошибка, работает только с включенным 32-битным приложением.
  • Windows Server 2008 Standard R2 x64 - ошибка подтверждена, работает только с включенным 32-битным приложением
  • Стандарт Windows Server 2008 x86 - работает

РЕДАКТИРОВАТЬ 2 (вопрос решен)

Решено Noseratio:

Правильный тип параметров ppwzMimeOut и pBC должен быть System.IntPtr вместо System.UInt32.

Я знаю, что System.UInt32 вызывает проблемы во всех 64-битных веб-приложениях, но я не знаю почему.

Если кто-то знает причину этих проблем, может объяснить это лучше в комментарии?

Заранее спасибо

Ответ 1

Если вы использовали подпись 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
);

Я предпочел бы использовать defintion из 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.

Обратитесь к этой реализации, которая выглядит правильно.