Переименование файла сборки и сборка.Загрузочный файл

#c# #file-io #clr #.net-assembly

#c# #файл-ввод-вывод #среда clr #.net-сборка

Вопрос:

Итак, вот ситуация:

У меня есть сборка под названием Lib1.dll . По какой-то причине (не относящейся к вопросу) Мне пришлось переименовать имя файла сборки в Lib1New.dll , теперь при попытке загрузить переименованную сборку с помощью Assembly.LoadFile Я заметил, что среда CLR пытается загрузить Lib1.dll также.

Если Lib1.dll найдено в пути поиска, оно загружается в адресное пространство. Приложение работает нормально независимо от того, Lib1.dll был найден или нет. (Проблема в том, что если Lib1.dll обнаружено, что файл заблокирован и не может быть удален другими процессами).

введите описание изображения здесь

Я не понимаю, почему LoadFile выполняет поиск и загружает Lib1.dll . Предполагается, что LoadFile загружает содержимое файла сборки в указанное местоположение, почему он ищет файлы.

Документация MSDN для LoadFile:

Используйте метод LoadFile для загрузки и проверки сборок, которые имеют одинаковый идентификатор, но расположены по разным путям. LoadFile не загружает файлы в контекст LoadFrom и не разрешает зависимости с использованием пути загрузки, как это делает метод LoadFrom. LoadFile полезен в этом ограниченном сценарии, потому что LoadFrom нельзя использовать для загрузки сборок, которые имеют одинаковые идентификаторы, но разные пути; он загрузит только первую такую сборку.

Ответ №1:

Я предлагаю вам попробовать упростить вашу проблему, потому что я просто попытался воспроизвести вашу ситуацию и не столкнулся с проблемой. Я создал Lib.dll сборка, скомпилировал ее, создал консольное приложение, которое загрузило ее с помощью LoadFile, затем переименовал Lib.dll и ссылка консоли на него, чтобы «LibNew.dll «. Затем я повторно скомпилировал lib.dll и запустил консольное приложение. На тот момент я не смог удалить LibNew.dll , но я смог удалить Lib.dll .

Я подозреваю, что ваш Lib.dll возможно, загружает некоторую информацию из своей собственной сборки при запуске и внутренне использует для этого другую функцию загрузки, которая в конечном итоге находит оригинал Lib.dll . Но если у вас очень простая DLL, она не будет выполнять эту дополнительную нагрузку. В моей DLL есть функция, которую я смог вызвать, но я все еще видел результаты, о которых сообщалось выше. Вот мой код:

Консольное приложение:

 class Program
{
    static void Main(string[] args)
    {
        System.Reflection.Assembly assy = System.Reflection.Assembly.LoadFile(args[0]);
        Type class1 = assy.GetType("Lib.Class1");

        System.Reflection.MethodInfo myMethod = class1.GetMethod("MyMethod");
        Console.WriteLine(myMethod.Invoke(null, new object[] {"This is a string"}).ToString());

        Console.ReadLine();
    }
}
  

Библиотека:

 namespace Lib
{
public class Class1
{
    public static string MyMethod(string param)
    {
        return "Fixed: ["   param.Replace(" ", "-")   "]";
    }
}
}
  

Отслеживая только вызовы LoadImage, я вижу, что он не пытался загрузить Lib.dll:
Отслеживание процесса мониторинга вызовов LoadImage

Однако, отслеживая все события, я вижу, что он сделал проверку на Lib.dll в каталоге приложения. Отслеживание процесса мониторинга всех ссылок на DebugLib

Возможно, если вы поместите DLL в другой каталог, вы сможете принудительно изменить желаемое поведение? Однако, учитывая документацию, это странное поведение.

Комментарии:

1. Спасибо BlueMonkMN, в этом есть некоторый смысл. Если библиотека загружается динамически, то можно загрузить исходную библиотеку, но журнал process monitor, который я прикрепил к сообщению, был создан с использованием следующего Lib1 с использованием System; пространство имен Lib1 { открытый класс Class1 { public void sayHello() { Консоль. WriteLine(«Class1::sayHello»); } } } Можете ли вы запустить process monitor и проверить, пытается ли консольное приложение загрузить обе библиотеки DLL или нет.

2. Похоже, что он не нашел его, потому что у меня была DLL в каталоге, отличном от каталога приложения.

Ответ №2:

LoadFile использует поиск файлов Windows, а не .Разрешение сборки NET. Но он все еще выполняет поиск файла.

Это похоже на вызов, new FileStream() где вы можете передать имя файла, и он будет искать его в PATH и т.д., Если это относительный путь.

Комментарии:

1. LoadFile не работает с относительными путями, для этого требуется абсолютный путь к сборке, поэтому я не думаю, что приведенный выше ответ имеет отношение к этому вопросу. В любом случае, спасибо