Загрузка сборки во время выполнения не удается, когда я копирую DLL после запуска программы - PullRequest
8 голосов
/ 19 декабря 2010

Во время выполнения я загружаю сборку с

Assembly assembly = Assembly.LoadFrom(@"c:\MyFolder\MyAssembly.dll");

Это работает, если сборка находится в этой папке.

Если сборка НЕ ​​находится в папке, я, конечно, получаю исключение, сообщающее, что сборка или одна из ее зависимостей не найдены.

Я ловлю исключение и отображаю сообщение об ошибке для пользователя. Программа продолжает работать.

Если я сейчас скопирую отсутствующую сборку в папку «c: \ MyFolder», пока программа еще работает, и снова активирую функцию, которая выполняет строку выше , я получаю то же исключение - System.IO.FileNotFoundException - еще раз, что сборка не может быть найдена, хотя DLL теперь находится в папке .

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

Таким образом, проблема, похоже, связана с первым неудачным вызовом Assembly.LoadFrom.

В чем может быть причина такого поведения и что я могу сделать, чтобы решить проблему?

Заранее спасибо за помощь!

Редактировать: еще одна деталь:

Я добавил File.Exists тест:

string filename = @"c:\MyFolder\MyAssembly.dll";
bool test = File.Exists(filename);
Assembly assembly = Assembly.LoadFrom(filename);

test возвращает true, но Assembly.LoadFrom выдает FileNotFoundException.

Ответы [ 2 ]

7 голосов
/ 19 декабря 2010

Функция, а не ошибка.Это контрмеры DLL Ада.Оперативный термин «загрузка контекста», поищите фразу Сьюзен Кук , чтобы узнать о ней больше.В двух словах, CLR запоминает предыдущие попытки загрузить сборку.Прежде всего, он записывает успешные привязки и гарантирует, что точная та же сборка будет загружена снова, даже если содержимое диска изменилось.Вы можете, без сомнения, увидеть выгоду от этого, внезапно получить другую сборку почти всегда катастрофически.Он также запоминает их, по той же причине, что и в будущем их подведет.Не существует документированного способа сброса контекста загрузки, о котором я знаю.Assembly.LoadFile () загружает сборки без контекста загрузки.Но это вызывает целый ряд других проблем, вы действительно не хотите его использовать.

5 голосов
/ 19 декабря 2010

Чтобы обойти кэширование CLR при LoadFrom попытках, вы можете немного изменить свой код, чтобы использовать перегрузку Assembly.Load(byte[] rawAssembly).

Примерно так:

Assembly LoadWithoutCache(string path)
{
    using (var fs = new FileStream(path, FileMode.Open))
    {
        var rawAssembly = new byte[fs.Length];
        fs.Read(rawAssembly, 0, rawAssembly.Length);
        return Assembly.Load(rawAssembly);
    }
}
...