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