Неуправляемые DLL не загружаются на сервере ASP.NET

Этот вопрос относится к веб-сайту ASP.NET, первоначально разработанному в VS 2005 и теперь в VS 2008.

Этот веб-сайт использует две неуправляемые внешние DLL, которые не являются .NET, и у меня нет исходного кода для их компиляции и они должны использовать их как есть.

Этот веб-сайт отлично работает в Visual Studio, правильно размещая и получая доступ к этим внешним DLL. Однако, когда веб-сайт публикуется на веб-сервере (запуск IIS6 и ASP.NET 2.0), а не на ПК разработки, он не может найти и получить доступ к этим внешним DLL, и я получаю следующую ошибку:

Unable to load DLL 'XYZ.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

Внешние DLL файлы находятся в каталоге bin на веб-сайте, а также управляемые DLL файлы, которые обертывают их и все другие DLL файлы для веб-сайта.

Поиск этой проблемы показывает, что многие другие люди, похоже, имеют ту же проблему, что и доступ к внешним не-NET-библиотекам с веб-сайтов ASP.NET, но я не нашел решение, которое работает.

Я пробовал следующее:

  • Запуск DEPENDS для проверки зависимостей, чтобы установить, что первые три находятся в каталоге System32 в пути, последний находится в .NET 2 рамки.
  • Я разместил две библиотеки DLL и их зависимости в System32 и перезагрузили сервер, но веб-сайт все еще не удалось загрузить эти внешние DLL.
  • Предоставил полные права на ASPNET, IIS_WPG и IUSR (для этого сервера) до каталог корзины веб-сайтов и перезагрузка, но веб-сайт по-прежнему не может загрузите эти внешние DLL.
  • Добавлены внешние библиотеки DLL как существующие элементы для проектов и установлены их свойство "Копировать в вывод" в "Копировать всегда" и веб-сайт все еще не могут найти DLL.
  • Также установите для свойства "Свойство действия" значение "Встроенный ресурс" и веб-сайт по-прежнему не может найти библиотеки DLL.

Любая помощь с этой проблемой будет принята с благодарностью!

Ответ 1

Попробуйте поместить dll в каталог \System32\Inetsrv. Это рабочий каталог для IIS на Windows Server.

Если это не сработает, попробуйте поместить dll в каталог System32 и файлы зависимостей в каталог Inetsrv.

Ответ 2

Это происходит из-за того, что управляемые dll получают теневое копирование во временное место в каталоге .NET Framework. Подробнее см. http://msdn.microsoft.com/en-us/library/ms366723.aspx.

К сожалению, неуправляемые dll не копируются, и процесс ASP.NET не сможет найти их, когда ему нужно их загрузить.

Одно простое решение - поместить неуправляемые DLL в каталог, находящийся в системном пути (введите "путь" в командной строке, чтобы увидеть путь на вашем компьютере), чтобы они могли быть найдены процессом ASP.NET, Каталог System32 всегда находится в пути, поэтому всегда нужно работать с неуправляемыми dll, но я бы рекомендовал добавить в путь другую папку, а затем добавить туда DLL, чтобы предотвратить загрязнение каталога System32. Один из больших недостатков этого метода заключается в том, что вам нужно переименовать неуправляемые DLL для каждой версии вашего приложения, и вы можете быстро создать свой собственный адский аддон.

Ответ 3

В качестве альтернативы размещению dll в папке, которая уже находится в пути (например, system32), вы можете изменить значение пути в своем процессе, используя следующий код

System.Environment.SetEnvironmentVariable("Path", searchPath + ";" + oldPath)

Затем, когда LoadLibrary пытается найти неуправляемую DLL, он также сканирует searchPath. Это может быть предпочтительнее создавать беспорядок в System32 или других папках.

Ответ 4

Добавляя к ответу Matt, вот что, наконец, работало для меня для 64-битного сервера 2003/IIS 6:

  • убедитесь, что ваши dlls/asp.net - это одна и та же версия (32/64 бит).
  • Поместите неуправляемые dll в inetsrv dir (обратите внимание, что в 64-битных окнах это находится под syswow64, хотя создается каталог sys32/inetsrv)
  • Оставьте управляемые DLL в /bin
  • Убедитесь, что оба набора DLL имеют права на чтение/выполнение.

Ответ 5

Посмотрите FileMon или ProcMon и фильтр на имена проблемных DLL. Это покажет вам, какие каталоги сканируются при поиске DLL, и о любых проблемах, которые могут возникнуть у вас.

Ответ 6

Другой вариант - встраивание родной DLL в качестве ресурса в управляемую DLL. Это сложнее в ASP.NET, поскольку для ее выполнения требуется запись во временную папку во время выполнения. Техника объясняется в другом ответе SO.

Ответ 7

Запустите DEPENDS на XYZ.dll прямо в том месте, где вы его развернули. Если это ничего не обнаруживает, используйте инструмент fuslogvw в SDK платформы для отслеживания ошибок загрузчика. Кроме того, журналы событий иногда содержат информацию о сбоях загрузки DLL.

Ответ 9

Я столкнулся с той же проблемой. И я попробовал все вышеперечисленные опции, скопировав в system32, inetpub, установив путь и т.д. Ничего не получилось. Эта проблема окончательно решена путем копирования неуправляемой dll в каталог bin веб-приложения или веб-службы.

Ответ 10

После борьбы весь день над этой проблемой и, наконец, я нашел решение, которое мне подходит. Это просто тест, но метод работает.

namespace TestDetNet
{
    static class NativeMethods
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);


        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
    }

    public partial class _Default : System.Web.UI.Page
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        private delegate int GetRandom();

        protected System.Web.UI.WebControls.Label Label1;
        protected void Page_Load(object sender, EventArgs e)
        {
            Label1.Text = "Hell'ou";
            Label1.Font.Italic = true;
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            if (File.Exists(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll")) {
                IntPtr pDll = NativeMethods.LoadLibrary(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll");
                if (pDll == IntPtr.Zero) { Label1.Text =  "pDll is zero"; }
                else
                {
                  IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "GetRandom");
                  if (pAddressOfFunctionToCall == IntPtr.Zero) { Label1.Text += "IntPtr is zero";   }
                  else
                  {
                    GetRandom _getRandom = (GetRandom)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(GetRandom));

                    int theResult = _getRandom();

                    bool result = NativeMethods.FreeLibrary(pDll);
                    Label1.Text = theResult.ToString();
                  }
                }
          }
        }
    }
}