Ссылка .NET "Скопировать локальную" True/False Установить на основе содержимого GAC
У нас была очень интересная проблема с проектом Win Forms. Это было разрешено. Мы знаем, что произошло, но мы хотим понять, почему это произошло. Это может помочь другим людям в будущем, у которых есть аналогичная проблема.
Проект WinForms завершился неудачно на двух наших клиентских ПК. Ошибка была неясной ошибкой kernel.dll. Проект отлично работает на 3 других ПК.
Мы обнаружили, что в нашей папке выпуска отсутствовала .DLL(log4net.dll - очень популярная библиотека регистрации с открытым исходным кодом). Ранее это было в нашей папке выпуска. Почему он отсутствовал в этом последнем выпуске?
Он отсутствовал, потому что я должен был установить программу в своем блоке Dev, которая использовала log4net.dll, и она была добавлена в глобальный кэш сборок.
Когда я проверил ссылки на решение для log4net.dll, они были изменены на "copy local = FALSE". Они должны были автоматически измениться, поскольку log4net.dll присутствовал в моем GAC.
Здесь, где начинается мой вопрос:
Почему моя ссылка для log4net.dll изменилась с COPY LOCAL = TRUE на COPY LOCAL = FALSE? Я подозреваю это, потому что он был добавлен в мой GAC другой программой.
Как мы можем предотвратить это снова? Теперь, если я установлю часть программного обеспечения, использующего общую библиотеку, и она добавит ее в мой GAC, тогда мои SLN, которые ссылаются на эту DLL, будут меняться от Copy Local TRUE до FALSE.
Ответы
Ответ 1
Это произошло потому, что не имеет смысла копировать Local = True, если сборка установлена в GAC. Поскольку эта локальная копия никогда не будет использоваться, GAC всегда будет искать сначала. Если оставить его без изменений, это вызовет серьезную путаницу, вы бы подумали, что используете локальную копию, но вместо этого получаете другую. Изменение этого также вызывает путаницу, если вы этого не заметите, возможно, это могло быть адресовано с полем сообщения при времени загрузки решения.
Log4net - нарушитель спокойствия, существует множество версий в дикой природе без какой-либо процедуры развертывания, которая гарантирует, что эти версии не кусают друг друга. Что-то Apache, по-видимому, просто не хотел обращаться, оставив его вместо программиста. Наличие продуктов, которые зависят от Log4net и что-то делать с предполагаемым риском DLL Hell, несколько неизбежно. Предоставление вам проблемы DLL Hell в ответ.
Нет простых простых ответов, не зная, что установлено на вашем компьютере. Рассмотрите возможность публикации на connect.microsoft.com, чтобы запросить предупреждение, когда Visual Studio автоматически обновляет свойство Copy Local. Это разумный вопрос.
Ответ 2
Во время выполнения сборки должны быть в одном из двух местоположений: путь вывода проекта или глобальный кэш сборок (см. Работа с сборками и глобальный кэш сборок). Если проект содержит ссылку на объект, который не находится в одном из этих местоположений, тогда, когда проект построен, ссылка должна быть скопирована в выходной путь проекта. Свойство CopyLocal указывает, должна ли эта копия быть сделана. Если значение истинно, ссылка копируется. Если false, ссылка не копируется.
Назначенное проектом значение CopyLocal определяется в следующем порядке:
- Если ссылка - это другой проект, называемый ссылкой на проект, то значение истинно.
- Если сборка найдена в глобальном кеше сборки, значение равно false.
- В качестве специального случая значение для ссылки mscorlib.dll неверно.
- Если сборка найдена в папке Framework SDK, значение равно false.
В противном случае значение будет истинным.
С уважением...
Muse VSExtensions
Ответ 3
Я просто столкнулся с этой проблемой на наших серверах сборки. Это очень раздражает (и неожиданно) поведение Visual Studio. Два обходных пути:
- Удалите сборки из GAC.
- Добавьте событие PostBuild, чтобы вручную скопировать сборки в выходной каталог.
Ответ 4
Я нашел решение для нас на наших серверах сборки.
Проблема:
В конкретную дату без причины (теперь я предполагаю, что файл был добавлен в GAC), сборка System.Web.MVC.dll исчезла из многих наших проектов. Я уверен, что это относится к любой DLL с проблемой.
Решение:
В визуальной студии изменить ссылку (при условии, что Copy Local уже True).
- Изменить копию Local = True для копирования Local = False
- Изменить копию Local Back to True
- Обратите внимание, что в файле .csproj добавлен
<Private>True</Private>
.
- Скомпилируйте сейчас, и вы увидите, что dll действительно включается, хотя сообщение остается тем же.
Solution2:
Добавьте свойство <Private>True</Private>
вручную.
Выводы:
Мое понимание <Private>
заключается в том, что это Копировать Локально, поэтому, если Копировать Локальный = Истина, нужно добавить частное свойство, но в нашем случае, по крайней мере, это не так.
Дополнительные соображения:
- Протестировано с использованием Visual Studio 2013 и 2015.
- Протестировано с использованием msbuild 12 и 14.
- Протестировано с использованием шаблона сборки TFS.
- Наш код был обновлен с визуальной студией с 2008 по 2015 год, возможно, флаг заблудился где-то в то время, но проблема не началась, пока сборка не была добавлена в 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>
Ответ 5
Можете ли вы убедиться, что ваш используется, добавив hintpath в файл msbuild/proj?
Из приведенной выше ссылки:
HintPath: относительный или абсолютный путь сборки.