Вызов 32-битных неуправляемых DLL-файлов из C # случайно - PullRequest
0 голосов
/ 01 июня 2010

У меня проблема при вызове 32-битных Delphi DLL-файлов с веб-сайта C #. Код обычно работает нормально, но иногда я получаю сообщение об ошибке,

* Невозможно загрузить DLL '': указанный модуль не найден. (Исключение из HRESULT: 0x8007007E).

Эта проблема сохраняется до тех пор, пока я не перезапущу пул приложений для сайта, а затем он снова работает нормально.

На том же сервере также есть веб-служба, которая вызывает тот же набор файлов DLL. Этот веб-сервис, похоже, не имеет той же проблемы, что и веб-сайт.

Оба приложения используют .NET Framework 3.5, отдельные пулы приложений в IIS .

Вот код, который я использую, чтобы обернуть файлы DLL:

public sealed  class Mapper
{
    static Mapper instance = null;

    [DllImport("kernel32.dll")]
    private static extern bool SetDllDirectory(string lpPathName);

    private Mapper()
    {
        SetDllDirectory(ConfigManager.Path);
    }

    public static Mapper Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Mapper();
            }
            return instance;
        }
    }

    public int Foo(string bar, ref double val)
    {
        return Loader.Foo(bar, ref val);
    }
}


public static class Loader
{
    [DllImport("some.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, EntryPoint = "foo")]
    public static extern int Foo(string bar, ref double val);
}

Тогда я называю это так:

double val = 0.0; 
Mapper.Instance.Foo("bar", ref val);

Почему это "случайно" Невозможно загрузить DLL '': указанный модуль не найден. (Исключение из HRESULT: 0x8007007E). ?

Другая проблема заключается в том, что мне не удалось воспроизвести проблему в среде разработки. Я подумал, что из-за того, что два приложения вызывают одни и те же файлы DLL, могут возникать некоторые блокировки. Чтобы воспроизвести это, я создал приложение, которое порождало несколько потоков и неоднократно вызывало 32-битные DLL-файлы, а затем использовал веб-сайт для вызова тех же DLL-файлов. Я все еще не мог воспроизвести проблему.

Некоторые возможные исправления, о которых я могу подумать:

  1. Оберните 32-битные файлы DLL в веб-сервисе (потому что веб-сервис, похоже, не страдает от той же проблемы). Но это может оказаться бесполезным, если выяснится, что веб-служба также дает сбой.
  2. Настройте сервер состояний для состояния сеанса и периодически перезагружайте пул приложений для сайта. Это не устраняет проблему, а только позволяет ее избежать.
  3. Оберните файлы DLL в файл EXE и вызовите этот файл EXE. Тогда я не должен получить ту же проблему. Но это также кажется хакерским решением.
  4. Реализовать класс mapper по-другому? Но как еще мне делать звонок? Другим недостатком является то, что другие приложения используют этот маппер, поэтому мне тоже нужно изменить там код.

Что мне делать?

Ответы [ 2 ]

1 голос
/ 01 июня 2010

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

  • Используемому файлу DLL необходима библиотека времени выполнения, которая недоступна на момент загрузки (например, библиотека времени выполнения Visual C ++). Вам нужна точная версия библиотеки. Например, если ваш файл DLL написан с использованием среды выполнения Visual Studio 2008 с пакетом обновления 1 (SP1), вам нужна точно такая же версия.

  • Одна из зависимостей файла DLL недоступна. Вы можете проверить это с помощью Dependency Walker .

  • Кроме того, вы должны быть уверены, что ваш DLL-файл и вызывающее приложение все 32-битные или 64-битные. Иногда я получаю ту же ошибку, когда хочу вызвать 32-битный файл DLL из 64-битного приложения.

Я знаю, что это не совсем ваш ответ, но я надеюсь, что это поможет вам найти решение.

0 голосов
/ 08 июля 2010

Чтобы исправить эту проблему (теперь это перестало происходить), я оставил код сопоставления как есть, но в вызывающем приложении я вручную установил путь (даже если DLL-файл сопоставления делает это большую часть времени).

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

private static void AddEnvironmentPaths(string[] paths)
{
    string path = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
    path += ";" + string.Join(";", paths);

    Environment.SetEnvironmentVariable("PATH", path);
}

Что странно, так это то, что класс картостроителя работает большую часть времени, но иногда останавливается. Добавление пути с помощью приведенного выше кода, похоже, решило проблему.

...