MSBuild не копирует ссылки (файлы DLL), если использует зависимости проекта в решении - PullRequest
263 голосов
/ 15 июля 2009

У меня есть четыре проекта в моем решении Visual Studio (все ориентированы на .NET 3.5) - для моей проблемы важны только эти два:

  1. MyBaseProject <- эта библиотека классов ссылается на сторонний DLL-файл (elmah.dll) </li>
  2. MyWebProject1 <- этот проект веб-приложения имеет ссылку на MyBaseProject </li>

Я добавил ссылку elmah.dll на MyBaseProject в Visual studio 2008, нажав «Добавить ссылку ...» → вкладку «Обзор» → выбрав «elmah.dll».

Свойства ссылки на Эльму следующие:

  • Псевдонимы - глобальные
  • Копировать локально - true
  • Культура -
  • Описание - Модули и обработчики ошибок (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 содержит элемент private со значением "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!)

Ответы [ 18 ]

166 голосов
/ 22 октября 2011

Я просто так с этим справляюсь. Перейдите в свойства вашей ссылки и сделайте это:

Set "Copy local = false"
Save
Set "Copy local = true"
Save

и все.

Visual Studio 2010 изначально не содержит: <private>True</private> в ссылочном теге и установка «copy local» в false приводит к созданию тега. После этого он установит для него значение true и false соответственно.

143 голосов
/ 11 января 2014

Я не уверен, почему это отличается при сборке между Visual Studio и MsBuild, но вот что я обнаружил, когда столкнулся с этой проблемой в MsBuild и Visual Studio.

Объяснение

Для примера сценария предположим, что у нас есть проект X, сборка A и сборка B. Сборка A ссылается на сборку B, поэтому проект X содержит ссылку как на A, так и на B. Кроме того, проект X включает код, который ссылается на сборку A (например, A.SomeFunction ()).Теперь вы создаете новый проект Y, который ссылается на проект X.

Таким образом, цепочка зависимостей выглядит следующим образом: Y => X => A => B

VisualStudio / MSBuild старается быть умным и привносить в проект Y только те ссылки, которые он обнаруживает как необходимые для проекта X;он делает это, чтобы избежать загрязнения ссылок в проекте Y. Проблема в том, что проект X на самом деле не содержит никакого кода, который явно использует сборку B (например, B.SomeFunction ()), VS / MSBuild не обнаруживает, что требуется BX и, следовательно, не копирует его в каталог bin проекта Y;он копирует только сборки X и A.

Решение

У вас есть два варианта решения этой проблемы, каждый из которых приведет к копированию сборки B в каталог bin проекта Y:

  1. Добавить ссылку на сборку B в проекте Y.
  2. Добавить фиктивный код в файл в проекте X, который использует сборку B.

Лично я предпочитаю вариант 2по нескольким причинам.

  1. Если в будущем вы добавите еще один проект, который ссылается на проект X, вам не нужно будет также указывать ссылку на сборку B (как это было бы привариант 1).
  2. У вас могут быть явные комментарии, говорящие о том, почему фиктивный код должен быть там, а не удалять его.Поэтому, если кто-то действительно удаляет код случайно (скажем, с помощью инструмента рефакторинга, который ищет неиспользуемый код), вы можете легко увидеть из исходного кода, что код требуется, и восстановить его.Если вы используете опцию 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);
    }
38 голосов
/ 16 июля 2009

Если вы не используете сборку непосредственно в коде, тогда Visual Studio, пытаясь быть полезным, обнаруживает, что она не используется, и не включает ее в вывод. Я не уверен, почему вы видите различное поведение между Visual Studio и MSBuild. Вы можете попробовать установить выходные данные сборки для диагностики и сравнить результаты и увидеть, где они расходятся.

Что касается ссылки на elmah.dll, если вы не ссылаетесь на нее напрямую в коде, вы можете добавить ее в качестве элемента в свой проект и установить для параметра «Действие сборки» значение Content, а для параметра «Копировать в выходной каталог» - Always.

14 голосов
/ 16 июля 2009

Взгляните на:

Эта ветка форума MSBuild, которую я создал

Вы найдете там мое временное решение / обходной путь!

(MyBaseProject требуется некоторый код, который ссылается на некоторые классы (что угодно) из elmah.dll для elmah.dll, копируемой в корзину MyWebProject1!)

8 голосов
/ 23 января 2012

У меня была такая же проблема.

Проверьте, совпадает ли базовая версия вашего проекта с базовой версией библиотеки DLL, на которую вы ссылаетесь.

В моем случае мой клиент был скомпилирован с использованием «Framework 4 Client», а DLL была в «Framework 4».

6 голосов
/ 19 июля 2012

Проблема, с которой я столкнулся, заключалась в том, что у меня есть проект, который зависит от проекта библиотеки. Чтобы построить, я следовал за этими шагами:

msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package

Это, конечно, означало, что мне не хватало dll-файлов моей библиотеки в bin и, самое главное, в zip-файле пакета. Я обнаружил, что это прекрасно работает:

msbuild.exe myproject.vbproj /T:Rebuild;Package

Я понятия не имею, почему эта работа или почему она не была вообще. Но надеюсь, что это поможет.

4 голосов
/ 12 февраля 2014

У меня точно такая же проблема, и это, как оказалось, вызвано тем, что 2 проекта в одном решении ссылались на другую версию сторонней библиотеки.

Как только я исправил все ссылки, все заработало отлично.

4 голосов
/ 14 августа 2013

Как отметил Алексей Бурцев в комментарии, все, что используется только в словаре ресурсов XAML, или, в моем случае, все, что используется только в XAML, а не в коде позади, не считается «используемым» MSBuild.

Так что просто добавление фиктивной ссылки на класс / компонент в сборке в некотором коде было достаточно, чтобы убедить MSBuild, что сборка действительно использовалась.

3 голосов
/ 02 августа 2013

Изменение целевого фреймворка с .NET Framework 4 Client Profile на .NET Framework 4 устранило эту проблему для меня.

Итак, в вашем примере: установите целевую платформу на MyWebProject1 равной .NET Framework 4

3 голосов
/ 08 декабря 2016

Используя схему deadlydog,

Y => X => A => B ,

моя проблема заключалась в том, что когда я собирал Y, сборки (A и B, все 15 из них) из X не показывались в папке bin Y.

Я получил решение, убрав ссылку X из Y, сохранив, собрав, затем повторно добавив ссылку X (ссылку на проект), и сохраните, соберите, и A и B начали появляться в папке bin Y. *

...