.NET ссылка "копировать локальный" True / False устанавливается на основе содержимого GAC

У нас была очень интересная проблема с проектом Win Forms. Она решена. Мы знаем, что произошло, но хотим понять, почему это произошло. Это может помочь другим людям в будущем, у которых есть аналогичная проблема.

проект WinForms не удался на 2 ПК нашего клиента. Ошибка была неясным ядром.ошибка dll. Проект отлично работал на 3 других ПК.

мы обнаружили, что .Dll файлы (такой как log4net.dll-Очень популярная библиотека журналов с открытым исходным кодом) отсутствовала в нашей папке release. Это было ранее в нашей папке release. Почему он отсутствовал в этом последнем выпуске?

Он отсутствовал, потому что я должен был установить программу на моем Dev box, который использовал log4net.dll и он был добавлен в глобальный кэш сборок.

когда я проверил ссылки решения для log4net.dll, они были изменены на "копировать local=FALSE". Они должны были измениться автоматически, потому что log4net.dll присутствовала в моем GAC.

вот где мой вопрос начинается:

Почему моя ссылка для log4net.dll изменяется с COPY LOCAL = TRUE на COPY LOCAL = FALSE? Я подозреваю, что это потому, что он был добавлен в мой GAC другой программой.

Как мы можем предотвратить это снова? В настоящее время, если я устанавливаю часть программного обеспечения, которая использует общую библиотеку, и она добавляет ее в мой GAC, то мои SLNs, которые ссылаются на эту DLL, изменятся с Copy Local TRUE на FALSE.

5 ответов


Это произошло, потому что нет никакого смысла копировать Local = True, если сборка установлена в GAC. Поскольку эта локальная копия никогда не будет использоваться, сначала всегда выполняется поиск GAC. Если оставить его без изменений, это вызовет большую путаницу, вы подумаете, что используете локальную копию, но вместо этого получите другую. Изменение его также вызывает путаницу, если вы его не заметили, что, возможно, было устранено с помощью окна сообщения во время загрузки решения.

такой как log4net является troublemaker, есть слишком много версий в дикой природе без какой-либо процедуры развертывания, которая гарантирует, что эти версии не кусают друг друга. Что-то Apache, по-видимому, просто не хотел обращаться, оставив это программисту. Наличие продуктов, которые зависят от Log4net и что-то делают с воспринимаемым риском DLL Hell, несколько неизбежно. Давая вам проблему DLL Hell взамен.

нет чистых простых ответов, помимо того, что известно, что установлено на ваша машина. Рассмотрите возможность публикации в connect.microsoft.com запрашивать предупреждение, когда Visual Studio автоматически обновляет локальное свойство Copy. Это разумный вопрос.


во время выполнения сборки должны находиться в одном из двух расположений: выходной путь проекта или глобальный кэш сборок (см. раздел Работа со сборками и глобальный кэш сборок). Если проект содержит ссылку на объект, который не находится в одном из этих мест, то при построении проекта, ссылка должна быть скопирована в выходной путь проекта. Свойство CopyLocal указывает, нужно ли делать эту копию. Если значение равно true, ссылка копируется. Если false, ссылка не копируется.

присвоенное проекту значение CopyLocal определяется в следующем порядке:

  1. если ссылка является другим проектом, называемым ссылкой проект-проект, то значение равно true.
  2. если сборка находится в глобальном кэше сборок, значение false.
  3. в частном случае значение для mscorlib.ссылка dll является ложной.
  4. если сборка найдена в папке Framework SDK, тогда значение false. В противном случае значение true.

с уважением... Muse VSExtensions


Я нашел решение для нас на наших серверах строить.

проблема: В определенную дату без причины (теперь я предполагаю, что файл был добавлен в GAC) система сборки.Сеть.В MVC.dll исчезла из многих наших проектов. Я уверен, что это относится к любой dll с проблемой.

решение: В visual studio измените ссылку (при условии, что локальная копия уже верна).

  1. изменить копировать Local = True, чтобы скопировать Local = False
  2. Изменить Скопировать Local Back to True
  3. обратите внимание на .csproj файл a это.
  4. скомпилируйте сейчас, и вы увидите, что dll действительно включается, хотя сообщение остается прежним.

Solution2: Добавьте <private>True</private> свойства вручную.

выводы: Мое понимание <Private> это локальная копия, поэтому, если Copy Local = True, должно быть добавлено частное свойство, но в нашем случае, по крайней мере, это не было.

дополнительные Соображения:

  1. протестировано с помощью Visual Studio 2013 и 2015.
  2. протестировано с помощью msbuild 12 и 14.
  3. протестировано с помощью шаблона сборки TFS.
  4. наш код был обновлен с 2008 по 2015 visual studio, флаг, возможно, был испорчен где-то за это время, но проблема не началась, пока сборка не была добавлена в GAC каким-то образом.

Конечный Результат:

<Reference Include="System.Web.Mvc, Version=4.0.0.1, Culture=neutral,PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
 <HintPath>packages\Microsoft.AspNet.Mvc.4.0.40804.0\lib\net40\System.Web.Mvc.dll        </HintPath>
        <Private>True</Private>
    </Reference>

Я только что столкнулся с этой проблемой на наших серверах сборки. Это очень раздражающее (и неожиданное) поведение Visual Studio. Два обходных пути:

  1. удалите сборки из GAC.
  2. добавьте событие PostBuild, чтобы вручную скопировать сборки в выходной каталог.

можете ли вы убедиться, что ваш используется, добавив hintpath в файл msbuild/proj?

из приведенной выше ссылки:

HintPath : относительная или абсолютный путь сборки.