Ссылка на стороннюю сборку, которая не находится в корневом каталоге

У меня есть проект C# Visual Studio 2010, который создает .exe, и этот проект использует некоторую стороннюю библиотеку классов. Мой проект находится в: /MyFramWork/tests/test1 Сторонняя библиотека находится по адресу: /MyFrameWork/bin/utils/

Я добавляю ссылку в библиотеку, используя Ссылки->Добавить ссылку->Обзор. Я вижу, что в файле проекта все в порядке: ....\bin\utils\log4net.dll False

Я хотел бы сослаться на стороннюю библиотеку, не используя опцию «Копировать локально». Однако, если я не использую эту опцию, библиотека не будет найдена, и я получу исключение.

Мой вопрос: есть ли способ указать, что сторонняя библиотека должна быть найдена в ....\bin\utils. Кажется, что когда .exe получает сборку, информация из .csproj теряется.


person Potzon    schedule 07.04.2012    source источник
comment
Почему вы не хотите использовать локальное копирование?   -  person thecoop    schedule 07.04.2012
comment
Вы можете вызвать DLL Hell, написав обработчик события AppDomain.CurrentDomain.AssemblyResolve. Назначьте его в методе Main().   -  person Hans Passant    schedule 07.04.2012
comment
У меня та же проблема - сторонние сборки .NET не зарегистрированы в GAC. Мы хотим расширить стороннее приложение веб-службой, установленной в другом каталоге. У меня нет другого выбора, кроме как скопировать файлы в каталог BIN веб-службы. Если я обновлю стороннее программное обеспечение, мне также придется обновить веб-службу. Облом.... Если бы я только мог сослаться на сторонние .NET dll, где они находятся естественным образом. Вот где у WIN32 dll есть преимущество.   -  person barrypicker    schedule 22.02.2013


Ответы (4)


По умолчанию приложения .NET ищут свои зависимости только в двух местах: в каталоге EXE и в GAC (глобальный кэш сборок).

У вас есть три варианта:

  • Вы можете убедиться, что зависимость копируется в тот же каталог, что и ваш EXE (это то, что делает Copy Local). В большинстве случаев это лучший выбор, поэтому он используется по умолчанию, когда вы ссылаетесь на сборку, которой еще нет в GAC.
  • Вы можете установить свою зависимость в GAC, используя gacutil. Это может быть хорошим выбором, если ваша зависимость не будет меняться, будет находиться в другом месте на каждой машине разработки (т. проекты. Но это большая проблема, если зависимость все еще находится в стадии активной разработки и часто меняется. Вам также необходимо поместить DLL в GAC на каждом компьютере, на котором вы развертываете свое приложение.
  • Вы можете настроить поведение загрузки зависимостей, чтобы оно выглядело в других местах, как отметил Ханс в своем комментарии. Это расширенный вариант, который сопряжен с совершенно новым набором головных болей.

Обычно вы просто используете Copy Local; это очень разумное значение по умолчанию. Вам нужна достаточно веская причина, чтобы сделать что-то другое.

person Joe White    schedule 07.04.2012
comment
Я не хочу использовать локальную копию, потому что хочу, чтобы все .exe и .dll, которые я создаю, также находились в каталоге /MyFrameWork/bin/. Например, этот .exe при сборке копируется внутрь /MyFrameWork/bin/tests. Но я чувствую, что этого не должно быть? Я просто хочу сказать своему .exe, что он должен искать .dll в ../../bin/utils. Может нет пути? Также я не хочу использовать GAC, потому что хочу, чтобы пользователи, получающие файлы из системы управления версиями, могли сразу начать их использовать. - person Potzon; 07.04.2012
comment
Я видел статью: support.microsoft.com/kb/837908 Кажется, я могу использовать файл конфигурации приложения (.config) с тегами ‹codeBase›. Я напишу, если это то, что я ищу. - person Potzon; 07.04.2012
comment
Чувак, если ты хочешь собрать все свои EXE и DLL в один каталог, то в первую очередь делай это так — зайди в свойства проекта > вкладка «Сборка» и укажи выходной каталог. Тогда вам не нужно беспокоиться о том, является ли это локальным копированием или нет, потому что все уже находится в одном каталоге. - person Joe White; 07.04.2012
comment
Да, но я надеялся сохранить какую-то структуру каталогов в этом /bin. Например, /bin/устройства; /бен/тесты; /bin/utils и т. д. Однако, если я добавлю подкаталоги в /bin, мне понадобится какой-то способ ссылки на сборки. - person Potzon; 11.04.2012
comment
Я отмечаю это как ответ. Мое решение немного отличается, но все же решил собрать все библиотеки в одном месте. Что я сделал: Двоичные файлы хранятся в: /framework/bin/lib/ Тесты хранятся в: /framework/bin/tests/ Я использую переменную среды DEVPATH, чтобы указать на /framework/bin/lib/. Таким образом, когда тесты запускаются, они могут найти библиотеки в каталоге /lib. - person Potzon; 16.04.2012

Используйте элемент <probing>, чтобы указать, где среда CLR должна искать ваши сборки. Единственное ограничение состоит в том, что сборки должны располагаться в подкаталогах базового каталога вашего приложения.

Например, если базовый каталог вашего приложения — C:\MyFramework, то ваши сборки могут находиться в C:\MyFramework\bin.

Ознакомьтесь с этой статьей, чтобы узнать, как среда CLR ищет сборки.

person Bernard    schedule 07.04.2012
comment
Проблема в том, что мой базовый каталог приложения не C:\MyFramework. Это больше похоже на C:\MyFramework\tests\test1 или C:\MyFramework\bin\tests\. Но я понимаю, что вы имеете в виду. Кажется, то, что я хочу сделать, не так уж и просто. Я читал, что могу использовать файл конфигурации приложения (.config) с тегами ‹codeBase›, но это слишком много накладных расходов, поскольку для этого требуются сборки со строгими именами. - person Potzon; 07.04.2012
comment
Я бы не стал использовать сборки со строгими именами только для этой цели. - person Bernard; 08.04.2012
comment
Отличный ответ. я видел это в нескольких программах - person Siarhei Kuchuk; 08.04.2012

Если вам нужно загрузить сборки из пользовательских расположений, вы можете попробовать метод Assembly.LoadFile.

Следующие ссылки могут быть полезны:

C# — правильный способ загрузки Сборка, поиск класса и вызов метода Run()

http://www.csharp-examples.net/reflection-examples/

person Anil Mathew    schedule 07.04.2012

Это я, Потзон. Я все еще исследую эту невероятно глупую проблему.

Я надеялся на какое-то элегантное решение. Я собираюсь построить довольно большой фреймворк с большим количеством сборок, которые будут размещены внутри /Framework/bin/. Однако я хотел иметь некоторую структуру каталогов внутри каталога, например, /bin/utils, /bin/test, /bin/devices/ и так далее.

Одно из возможных решений, которое я нашел, — определить переменную окружения DEVPATH (см. здесь http://msdn.microsoft.com/en-us/library/cskzh7h6.aspx), но оказывается, что .net4 не использует эту переменную, когда сборка запускается независимо (вне Visual Studio), или, по крайней мере, это это случай для меня - я не могу заставить его работать.

Кажется, что решение поместить все сборки в каталог /bin без использования подкаталогов является лучшим. Я думаю, что я сдаюсь и просто сделаю это таким образом.

person Potzon1    schedule 11.04.2012