Сборка в GAC не копируется в выходные данные в проекте, который ссылается на проект, который ссылается на сборку GAC с CopyLocal = true

У меня есть «Проект A», который ссылается на System.Web.Mvc с CopyLocal = TRue. System.Web.Mvc находится в GAC как на моей локальной машине, так и на сервере сборки.

У меня также есть «Project B», который ссылается на «Project A» в выходных данных для «Project B». System.Web.Mvc не копируется во время сборки.

Я подозреваю, что это потому, что он находится в GAC. Это правда? А можно что-нибудь сделать, чтобы MSBuild скопировал его в папку вывода?

Я прочитал ответ Muse VsExtensions в этой теме, в котором говорится только о прямой ссылке на GAC, однако у нас есть косвенная ссылка через «Проект A»: Справочник .NET Копировать локальное значение True / False, установленное на основе содержимого GAC

Этот блог также связан с: http://deeperdesign.wordpress.com/2010/02/08/msbuild-assembly-dependencies-and-the-gac/


person khebbie    schedule 24.11.2011    source источник
comment
Интересно, что это происходит, даже если ваш проект ссылается на копию сборки, которой нет в GAC. VS видит, что копия живет в GAC, и не будет ее копировать.   -  person mhenry1384    schedule 31.10.2012
comment
Предположение верное. Если установить для MSBuild подробность диагностики, то при разрешении зависимостей будет получено This reference is not "CopyLocal" because it's registered in the GAC..   -  person makhdumi    schedule 11.07.2016


Ответы (3)


Одно из предложений, которое я видел вокруг этого, - это изменить все ваши проекты, чтобы они имели один и тот же путь вывода. Это имеет ограниченное значение, поскольку, если у вас есть цепочка зависимостей, например: Prj B> Prj A> Lib C Тогда это, вероятно, связано с тем, что Prj A используется в нескольких приложениях, для которых вы захотите, чтобы у каждого был свой собственный путь вывода.

Я решил проблему, используя MSBuild для компиляции и установив свойство OutDir для каждой сборки.

e.g. MSBuild projectB.csproj /p:OutDir=C:\AppBOutput\

Это поместит выходные данные для проекта B, его зависимых проектов (prj A) и prj As, скопирующих локальные зависимости в каталог C: \ AppBOutput \.

Почему это работает

При сборке проекта в Visual Studio и prj A, и prj B имеют собственный выходной каталог, например. prjA\bin\debug и prjB\bin\debug. Сохраненная в GAC сборка, заданная для copylocal, будет включена в выходной каталог проекта, который напрямую ссылается на нее (prjA). Но он не будет скопирован в выходной каталог проекта, ссылающегося на этот проект (prjB). Вот так и работает копирование ссылки на проект. Покопайтесь в целях MSBuild, и я уверен, что основная причина может быть найдена (извините, я не делаю этого сам).

Параметр /p:OutDir=C:\AppBOutput\ MSBuild устанавливает одинаковый выходной каталог для всех проектов. Делая это, вы обойдете поведение MSBuild в том, как он копирует выходные справочные данные от проекта к проекту. Вместо того, чтобы полагаться на MSBuild для копирования некоторого содержимого из prjA\bin\debug в prjB\bin\debug, вы просто заставляете все проекты выводить данные в один и тот же каталог.

person Snixtor    schedule 23.01.2012
comment
Непонятно, как это решит проблему. Настройка вывода всех проектов в один и тот же каталог в этом случае абсолютно ничего не дает. - person makhdumi; 11.07.2016
comment
Я получил несколько голосов против этого ответа после комментария @ Al-Muhandis, поэтому я отредактировал свой ответ, чтобы объяснить, почему это работает. Я также повторно протестировал решение сейчас четыре с половиной года спустя! с VS2015 и MSBuild 14.0 и могу убедиться, что оно по-прежнему ведет себя так же. Учитывая, что на MVC теперь предпочтительно ссылаться через NuGet, вопрос здесь является спорным, но ситуация остается такой же для других сборок, созданных GAC, например System.Xml.dll. - person Snixtor; 21.07.2016

Вы проверили файл .csproj, чтобы убедиться, что ссылка действительно содержит тег <Private>True</Private>? Copy local, к сожалению, имеет 3 состояния в xml - True, False и ... отсутствует.

person RasmusKL    schedule 24.11.2011
comment
На самом деле я добавил ‹Private› True ‹/Private› в файл csproj проекта B, где он ссылается на проект A. Но я все еще не получаю System.Web.Mvc в выходной папке. - person khebbie; 24.11.2011
comment
В проекте A у меня уже есть ‹Private› True ‹/Private› в файле csproj - person khebbie; 24.11.2011
comment
‹Private› True ‹/Private› не помогает в решении этой проблемы. - person stmax; 15.10.2014
comment
Спасибо. Это решило мою проблему. У меня был проект рабочей роли Azure, для которого в упакованном файле развертывания отсутствовали некоторые библиотеки DLL, на которые есть ссылки. Эти библиотеки DLL были в GAC на моем локальном компьютере по другим причинам (но их не будет в GAC в Azure). Несмотря на то, что в ссылке на проект было «Копировать локально», открытие файла проекта в «Блокноте» показало, что закрытый тег отсутствует для каждой библиотеки DLL. Я изменил свойство Copy Local на false, сохранил проект, затем снова на true и снова сохранил. Этого было достаточно, чтобы правильно вставить недостающие частные теги в XML-файл проекта .csproj и в Azure. - person cbailiss; 21.02.2015

Прагматичное решение (читай: взломать) состоит в том, что я сослался на System.Web.Mvc.dll в «Project B». Это определенно неправильное решение, поэтому, пожалуйста, дайте мне лучшее решение :-)

person khebbie    schedule 24.11.2011
comment
примите мой голос. вот как я справляюсь с этим дерьмом с давних пор. - person stmax; 15.10.2014
comment
Привет, хебби, ты нашел какое-нибудь решение для этого? - person Tobia Zambon; 04.11.2014
comment
это лучшее решение, чем помеченное как ответ - person liuhongbo; 05.12.2014