У меня есть четыре проекта в моем решении Visual Studio (каждый нацелен на .NET 3.5) - для моей проблемы важны только эти два:
- MyBaseProject <- эта библиотека классов ссылается на сторонний DLL-файл (elmah.dll)
- MyWebProject1 <- этот проект веб-приложения имеет ссылку на MyBaseProject
Я добавил ссылку elmah.dll на MyBaseProject в Visual studio 2008, нажав «Добавить ссылку ...» → вкладка «Обзор» → выбрав «elmah.dll».
Свойства ссылки Elmah следующие:
- Псевдонимы - глобальные
- Копировать локально - правда
- Культура -
- Описание - Модули и обработчики ошибок (ELMAH) для ASP.NET
- Тип файла - сборка
- Путь - D: \ webs \ otherfolder \ _myPath \ __ tools \ elmah \ Elmah.dll
- Решено - Верно
- Runtime версия - v2.0.50727
- Указанная версия - false
- Сильное имя - ложь
- Версия - 1.0.11211.0
В MyWebProject1 я добавил ссылку на проект MyBaseProject: «Добавить ссылку ...» → вкладка «Проекты» → выбрав «MyBaseProject». Свойства этой ссылки одинаковы, за исключением следующих элементов:
- Описание -
- Путь - D: \ webs \ CMS \ MyBaseProject \ bin \ Debug \ MyBaseProject.dll
- Версия - 1.0.0.0
Если я запускаю сборку в Visual Studio, файл elmah.dll копируется в каталог bin моего MyWebProject1 вместе с MyBaseProject.dll!
Однако, если я очищаю и запускаю MSBuild для решения (через D: \ webs \ CMS> C: \ WINDOWS \ Microsoft.NET \ Framework \ v3.5 \ MSBuild.exe / t: ReBuild / p: Configuration = Debug MyProject.sln ) elmah.dll отсутствует в каталоге bin MyWebProject1 - хотя сама сборка не содержит предупреждений или ошибок!
Я уже убедился, что .csproj MyBaseProject содержит закрытый элемент со значением «true» (это должен быть псевдоним « copy local » в Visual Studio):
<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\mypath\__tools\elmah\Elmah.dll</HintPath>
**<Private>true</Private>**
</Reference>
(Закрытый тег не появился в XML-файле .csproj по умолчанию, хотя Visual Studio сказал «копировать локальный» в значение true. Я переключил «копировать локальный» в значение «ложь» - сохранено - и снова установило значение «истина» - сохранить!)
Что не так с MSBuild? Как получить ссылку (elmah.dll), скопированную в корзину MyWebProject1?
Я НЕ хочу добавлять действие копирования после сборки в команду каждого проекта после сборки! (Представьте, что у меня много проектов зависит от MyBaseProject!)
Я не уверен, почему это отличается при сборке между Visual Studio и MsBuild, но вот что я обнаружил, когда столкнулся с этой проблемой в MsBuild и Visual Studio.
объяснение
Для примера сценария, скажем, у нас есть проект X, сборка A и сборка B. Сборка A ссылается на сборку B, поэтому проект X включает в себя ссылку как на A, так и на B. Кроме того, проект X включает код, который ссылается на сборку A (например, A. SomeFunction ()). Теперь вы создаете новый проект Y, который ссылается на проект X.
Таким образом, цепочка зависимостей выглядит следующим образом: Y => X => A => B
Visual Studio / MSBuild старается быть умным и привносить в проект Y только те ссылки, которые он обнаруживает как необходимые для проекта X; он делает это, чтобы избежать загрязнения ссылок в проекте Y. Проблема в том, что проект X на самом деле не содержит никакого кода, который явно использует сборку B (например, B.SomeFunction ()), VS / MSBuild не обнаруживает, что требуется B X и, следовательно, не копирует его в каталог bin проекта Y; он только копирует сборки X и A.
Решение
У вас есть два варианта решения этой проблемы, каждый из которых приведет к копированию сборки B в каталог bin проекта Y:
- Добавьте ссылку на сборку B в проект Y.
- Добавьте фиктивный код в файл в проекте X, который использует сборку B.
Лично я предпочитаю вариант 2 по паре причин.
- Если в будущем вы добавите еще один проект, который ссылается на проект X, вам не нужно будет также указывать ссылку на сборку B (как это было бы при использовании варианта 1).
- У вас могут быть явные комментарии, говорящие, почему фиктивный код должен быть там, а не удалять его. Поэтому, если кто-то действительно удаляет код случайно (скажем, с помощью инструмента рефакторинга, который ищет неиспользуемый код), вы можете легко увидеть из системы контроля версий, что код требуется, и восстановить его. Если вы используете вариант 1, а кто-то использует инструмент рефакторинга для очистки неиспользуемых ссылок, у вас нет комментариев; вы просто увидите, что ссылка была удалена из файла .csproj.
Вот пример «фиктивного кода», который я обычно добавляю, когда сталкиваюсь с такой ситуацией.
// DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
{
// Assembly A is used by this file, and that assembly depends on assembly B,
// but this project does not have any code that explicitly references assembly B. Therefore, when another project references
// this project, this project's assembly and the assembly A get copied to the project's bin directory, but not
// assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
// gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
var dummyType = typeof(B.SomeClass);
Console.WriteLine(dummyType.FullName);
}
Type dummyType = typeof(AssemblyA.AnyClass);
Console.WriteLine(dummyType.FullName);
enum
from B и предположил, что enum вставляется. Я добавил код, чтобы напрямую использовать тип из B, и это не помогло. Также всегда было так, что my X использует типы в A, которые подклассируют типы в B, поэтому я не могу понять, как компилятор считает, что B не требуется X и может быть проигнорировано. Это помешанные. Взгляни на:
Эту ветку форума MSBuild я начал
Вы найдете мое временное решение / обходной путь там!
(MyBaseProject требуется некоторый код, который ссылается на некоторые классы (что угодно) из elmah.dll для elmah.dll, копируемой в корзину MyWebProject1!)
Если вы не используете сборку непосредственно в коде, тогда Visual Studio, пытаясь быть полезным, обнаруживает, что она не используется, и не включает ее в вывод. Я не уверен, почему вы видите различное поведение между Visual Studio и MSBuild. Вы можете попробовать установить выходные данные сборки для диагностики и сравнить результаты, чтобы увидеть, где они расходятся.
Что касается ссылки на elmah.dll, если вы не ссылаетесь на нее напрямую в коде, вы можете добавить ее в качестве элемента в свой проект и установить для параметра «Действие сборки» значение Content
«Копировать в выходной каталог» Always
.
Я просто так с этим справляюсь. Перейдите в свойства вашей ссылки и сделайте это:
Set "Copy local = false"
Save
Set "Copy local = true"
Save
и это все.
Visual Studio 2010 изначально не помещается:
<private>True</private>
в тег ссылки и установка «копировать локальное» в значение false приводит к созданию тега. После этого он установит его в true и false соответственно.
<Private>true</Private>
но это, похоже, не влияло на MSBuild. В конце я просто добавил ссылки NuGet на проекты нижнего уровня. Have you tried turning it off and on again?
, и это сработало! У меня такая же проблема.
Проверьте, совпадает ли базовая версия вашего проекта с базовой версией библиотеки DLL, на которую вы ссылаетесь.
В моем случае мой клиент был скомпилирован с использованием «Framework 4 Client», а DLL была в «Framework 4».
У меня была такая же проблема, и dll была динамически загруженной ссылкой. Для решения проблемы я добавил «использование» с пространством имен DLL. Теперь dll копируется в выходную папку.
Проблема, с которой я столкнулся, заключалась в том, что у меня есть проект, который зависит от проекта библиотеки. Чтобы построить, я следовал за этими шагами:
msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package
Это, конечно, означало, что мне не хватало dll-файлов моей библиотеки в bin и, самое главное, в zip-файле пакета. Я нашел это работает отлично:
msbuild.exe myproject.vbproj /T:Rebuild;Package
Я понятия не имею, почему эта работа или почему это не было в первую очередь. Но надеюсь, что это помогает.
Я просто столкнулся с очень похожей проблемой. При компиляции с использованием Visual Studio 2010 файл DLL был включен в bin
папку. Но при компиляции с использованием MSBuild сторонний DLL-файл не был включен.
Очень расстраивает. Я решил это путем включения ссылки NuGet на пакет в мой веб-проект, хотя я не использую его непосредственно там.
Изменение целевой платформы с .NET Framework 4 Client Profile на .NET Framework 4 решило эту проблему для меня.
Итак, в вашем примере: установите целевую платформу на MyWebProject1 на .NET Framework 4
Как отметил в своем комментарии Алекс Бурцев, все, что используется только в словаре ресурсов XAML, или, в моем случае, все, что используется только в XAML, а не в коде, не считается «используемым» MSBuild.
Так что простого добавления фиктивной ссылки на класс / компонент в сборке в некотором коде было достаточно, чтобы убедить MSBuild в том, что сборка действительно использовалась.
Для этого необходимо добавить .targets
файл в проект и настроить его для включения в раздел включений проекта.
Смотрите мой ответ здесь для процедуры.
Ссылка на сборки, которые не используются во время сборки, не является правильной практикой. Вы должны увеличить свой файл сборки, чтобы он скопировал дополнительные файлы. Либо с помощью события после сборки, либо путем обновления группы свойств.
Некоторые примеры можно найти в другом посте
Включение всех ссылочных DLL-файлов из ваших проектных ссылок в проект Website - не всегда хорошая идея, особенно когда вы используете внедрение зависимостей : ваш веб-проект просто хочет добавить ссылку на интерфейсный файл / проект DLL, а не какую-либо конкретную реализацию DLL файл.
Потому что, если вы добавите ссылку непосредственно к файлу / проекту реализации DLL, вы не сможете помешать своему разработчику вызывать «новый» для конкретных классов файла / проекта реализации DLL, а не через интерфейс. Также вы указали «жесткий код» на вашем сайте, чтобы использовать реализацию.
У меня была точно такая же проблема, и это, как оказалось, было вызвано тем, что 2 проекта в одном решении ссылались на другую версию сторонней библиотеки.
Как только я исправил все ссылки, все работало отлично.
У меня была похожая проблема сегодня, и это, безусловно, не ответ на ваш вопрос. Но я хотел бы проинформировать всех и, возможно, дать искру понимания.
У меня есть приложение ASP.NET. Процесс сборки настроен на очистку, а затем сборку.
У меня есть два сценария Jenkins CI . Один для производства и один для постановки. Я развернул свое приложение для постановки, и все работало нормально. Развернут в производство и отсутствует файл DLL, на который есть ссылка. Этот файл DLL был просто в корне проекта. Не в любом хранилище NuGet. DLL была установлена в do not copy
.
Скрипт CI и приложение были одинаковыми между двумя развертываниями. После очистки и развертывания в промежуточной среде файл DLL был заменен в месте развертывания приложения ASP.NET ( bin/
). Это не относится к производственной среде.
Оказывается, в ветке тестирования я добавил шаг к процессу сборки, чтобы скопировать этот DLL-файл в bin
каталог. Теперь часть, которая заняла некоторое время, чтобы выяснить. Процесс CI не очищался сам по себе. DLL была оставлена в рабочем каталоге и была случайно упакована с файлом .zip ASP.NET. Производственная ветка никогда не копировала файл DLL таким же образом и никогда не развертывала это случайно.
TLDR; Проверьте и убедитесь, что вы знаете, что делает ваш сервер сборки.
Используя схему deadlydog,
Y => X => A => B ,
моя проблема заключалась в том, что когда я собирал Y, сборки (A и B, все 15 из них) из X не показывались в папке bin Y.
Я решил проблему, удалив ссылку X из Y, сохранив, собрав, затем повторно добавив ссылку X (ссылка на проект), и сохранив, собрав, и A и B начали появляться в папке bin Y.
Другой сценарий, в котором это проявляется, - это если вы используете более старый тип проекта «Веб-сайт» в Visual Studio. Для этого типа проекта он не может ссылаться на DLL-файлы, которые находятся за пределами его собственной структуры каталогов (текущей папки и вниз). Итак, в ответе выше, скажем, ваша структура каталогов выглядит так:
Где ProjectX и ProjectY являются родительскими / дочерними каталогами, а ProjectX ссылается на A.dll, которая, в свою очередь, ссылается на B.dll, а B.dll находится вне структуры каталогов, например, в пакете Nuget в корне (Packages), затем A. DLL будет включен, но B.dll не будет.
Убедитесь, что оба проекта находятся в одной и той же версии .net, также проверьте копию локального свойства, но это должно быть true
по умолчанию
Используя Visual Studio 2015 добавление дополнительного параметра
/ Deployonbuild = ложь
в командной строке msbuild исправлена проблема.