Настройка общей папки пакетов nuget для всех решений, когда некоторые проекты включены в несколько решений

Я использую NuGet для извлечения пакетов из внешних и внутренних источников пакетов, что очень удобно. Но я понял, что пакеты по умолчанию хранятся для каждого решения, что очень расстраивает, когда некоторые проекты со ссылками NuGet включены в несколько решений. Затем ссылки изменяются на другую папку пакета решений, которая может быть недоступна другому разработчику или машине сборки.

Я видел, что есть способы укажите общее расположение пакета (возможно, на корневом уровне проекта, мы используем TFS source control) с выпуском 2.1 NuGet, см. заметки . Я с помощью NuGet версии v2.7

но я попытался добавить nuget.конфигурационные файлы, не видя никакого эффекта от этого. Пакеты хранятся в папке решения. Я что-то пропустил? Кажется, что существуют различные структуры xml-узла для добавления в nuget.конфигурационный файл, в зависимости от того, кто отвечает вопрос: Schwarzie предлагает на еще один поток Stackoverflow:

<settings>
  <repositoryPath>....[relative or absolute path]</repositoryPath>
</settings>

примечания к выпуску NuGet 2.1 (см. ссылку выше) предлагают следующий формат:

<configuration>
  <config>
    <add key="repositoryPath" value="....[relative or absolute path]" />
  </config>
</configuration>

Я не знаю, какой из них, или любой, или оба будут работать в конце. Я пробовал оба на уровне решения. Может nuget.файл конфигурации должен быть размещен на корневом уровне проекта TFS или должен быть в каталоге решения? Кажется, что NuGet читает и применяет настройки из этих файлов в определенном по порядку, почему бы не добавить их в несколько уровней, где нугет.файл конфигурации на уровне решения переопределит файл на корневом уровне проекта TFS. Можно ли это уточнить?

мне нужно удалить все установленные пакеты, прежде чем эти ссылки будут работать? Я хотел бы, чтобы кто-то мог предоставить пошаговую инструкцию для перехода от использования nuget для конкретного решения к общей папке пакета, где проекты, принадлежащие нескольким решениям, могут найти необходимый nuget пакеты.

13 ответов


у меня аналогичная ситуация с внешними и внутренними источниками пакетов с проектами, на которые ссылаются более чем в одном решении. Я только что получил эту работу с одной из наших баз кода сегодня, и, похоже, работает с рабочими станциями разработчика и нашим сервером сборки. Ниже процесс имеет этот сценарий в виду (хотя это не должно быть трудно адаптироваться, чтобы иметь общую папку пакетов еще где).

  • кода
      На
  • Б
  • Проект C
  • решения
    • Решение 1
    • решение 2
    • решение 3
    • пакеты (это общий для всех решений)

обновленный ответ от NuGet 3.5.0.1484 с обновлением Visual Studio 2015 3

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

  • все, что необходимо передать в управление исходным кодом, отображается и отслеживается в решении
  • установка новых пакетов или обновление пакетов с помощью диспетчера пакетов в Visual Studio будет использовать правильный путь к репозиторию
  • после первоначальной настройки, никакого взлома .файлы csproj
  • нет модификации рабочей станции разработчика (код готов к сборке при выезде)

есть некоторые потенциальные недостатки, о которых нужно знать (я еще не испытал их, YMMV). См.Бенол это ответ и комментарии ниже.

Добавить NuGet.Config

вы захотите создать NuGet.Файл конфигурации в корне папки \Solutions\. Убедитесь, что это файл в кодировке UTF-8, который вы создаете, если вы не знаете, как это сделать, используйте Visual Studio Меню Файл - >Создать - >файл, а затем выберите шаблон XML-файла. Добавить в NuGet.Настройте следующее:

<?xml version="1.0" encoding="utf-8"?>
<configuration>  
  <config>
    <add key="repositoryPath" value="$\..\Packages" />
  </config>
</configuration>

для параметра repositoryPath можно указать абсолютный или относительный путь (рекомендуется) с помощью $ token. Токен $ основан на том, где находится NuGet.Config находится (токен $ фактически относительно на один уровень ниже расположение NuGet.Конфигурация.) Итак, если у меня есть \Solutions\NuGet.Config и я хочу \Solutions\Packages мне нужно будет указать $\..\Packages как значение.

Далее, вы хотите добавить папку решения к вам решение под названием Что-то вроде "NuGet" (щелкните правой кнопкой мыши на своем решении, добавить->Новая папка решения). Папки решений-это виртуальные папки, которые существуют только в решении Visual Studio и не создают фактическую папку на диске (и вы можете ссылаться на файлы из любого места). Щелкните правой кнопкой мыши на папке решения" NuGet", а затем добавьте - >существующий элемент и выберите \\NuGet Для Решения.Конфиг.

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

путем размещения NuGet.Конфигурационный файл в \Solutions\ над любым .sln-файлы, мы используем тот факт, что NuGet будет рекурсивно перемещаться по структуре папок вверх от "текущего рабочего каталога", ищущего NuGet.Файл конфигурации для использования. "Текущий рабочий каталог" означает здесь несколько разных вещей, одна из которых-путь выполнения NuGet.exe, а другой-расположение .sln файл.

переключение папки пакетов

во-первых, я настоятельно рекомендую вам просмотреть каждую папку решения и удалить все существующие \Packages\ folders (сначала вам нужно закрыть Visual Studio). Это облегчает задачу чтобы увидеть, где NuGet помещает вашу недавно настроенную папку \Packages\ и гарантирует, что любые ссылки на неправильную папку \Packages\ завершатся ошибкой и могут быть исправлены.

откройте решение в Visual Studio и начните перестраивать все. Игнорируйте все ошибки сборки, которые вы получите, это ожидается на данный момент. Однако это должно запустить функцию восстановления пакета NuGet в начале процесса сборки. Убедитесь, что папка \Solutions\Packages\ создана в указанном месте хотеть. Если нет, проверьте конфигурацию.

теперь для каждого проекта в вашем решении вы захотите:

  1. щелкните правой кнопкой мыши проект и выберите выгрузить проект
  2. щелкните правой кнопкой мыши проект и выберите Редактировать-xxx.csproj
  3. найдите любые ссылки на \packages\ и обновите их до нового местоположения.
    • большинство из них будут ссылками , но не все из них. Например, WebGrease и Microsoft.Bcl.Сборка будет иметь отдельные параметры пути, которые необходимо будет обновить.
  4. сохранить .csproj файл и щелкните правой кнопкой мыши на проекте и выберите перезагрузить проект

однажды все ваши .csproj файлы были обновлены, начать другую перестроить все, и вы не должны иметь больше ошибок сборки о недостающих ссылках. На этом этапе вы закончили, и теперь NuGet настроен на использование папки общих пакетов.

по состоянию на NuGet 2.7.1 (2.7.40906.75) с VStudio 2012

во-первых, нужно иметь в виду, что nuget.config не контролирует все параметры пути в системе пакетов nuget. Это было особенно сложно понять. В частности, проблема заключается в том, что msbuild и Visual Studio (вызов msbuild) не используют путь в nuget.config, а скорее переопределяют его в nuget.целевой файл.

Подготовка Среды

во-первых, я бы прошел через ваш папка решения и удалите все\ packages \ папки, которые существуют. Это поможет убедиться, что все пакеты явно устанавливаются в правильную папку и обнаруживают ссылки на неверные пути во всех решениях. Затем я бы удостоверился, что у вас установлено последнее расширение NuGet Visual Studio. Я бы также убедился, что у вас есть последний nuget.exe устанавливается в каждое решение. Откройте командную строку и перейдите на каждые $(SolutionDir)\ .NuGet\ folder и выполните следующие действия команда:

nuget update -self

установка общего пути к папке пакета для NuGet

откройте каждый $(SolutionDir)\ .из NuGet\NuGet для.Настройте и добавьте следующее внутри раздела :

<config>
    <add key="repositorypath" value="$\..\..\..\Packages" />
</config>

Примечание: вы можете использовать абсолютный или относительный путь. Имейте в виду, если вы используете относительный путь с $, что по отношению к на один уровень ниже расположение NuGet.Config (считаю, что это жук.)

установка общего пути к папке пакета для MSBuild и Visual Studio

откройте каждый $(SolutionDir)\ .из NuGet\NuGet для.цели и измените следующий раздел (обратите внимание, что для не-Windows есть еще один раздел ниже):

<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
    <!-- Windows specific commands -->
    <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
    <PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
    <PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
</PropertyGroup>

PackagesDir обновление

<PackagesDir>$([System.IO.Path]::GetFullPath("$(SolutionDir)\..\Packages"))</PackagesDir>

Примечание: GetFullPath разрешит наш относительный путь в абсолютный путь.

восстановление всех пакетов nuget в общую папку

Откройте командную строку и получите каждый $(SolutionDir)\ .NuGet и выполните следующую команду:

nuget restore ..\YourSolution.sln

на данный момент у вас должна быть одна папка \packages\ в вашем общем местоположении и ни в одной из ваших папок решения. Если нет, проверьте свои пути.

исправление ссылок на проекты

открыть каждый .файл csproj в текстовом редакторе и найдите любые ссылки на \packages и обновите их до правильного пути. Большинство из них будут ссылками , но не все из них. Например, WebGrease и Microsoft.Bcl.Сборка будет иметь отдельные параметры пути, которые необходимо будет обновить.

построить решение

откройте решение в Visual Studio и начать строить. Если он жалуется на отсутствующие пакеты, которые необходимо восстановить, не предполагайте, что пакет отсутствует и должен быть восстановлен (ошибка может вводить в заблуждение). Это может быть плохой путь в одном из ваших .csproj файл файлы. Проверьте это перед восстановлением пакета.

есть ошибка сборки о недостающих пакетах?

если вы уже проверили, что пути в вашем .файлы csproj верны, то у вас есть два варианта, чтобы попробовать. Если это результат обновления кода из системы управления исходным кодом, вы можете попробовать проверить чистую копию, а затем создать ее. Это сработало для одного из наших разработчиков, и я думаю, что в нем был артефакт .СУО файл или что-то подобное. Этот другой вариант-вручную принудительно восстановить пакет с помощью командной строки .папка nuget рассматриваемого решения:

nuget restore ..\YourSolution.sln

вместо установки общего местоположения пакета для всех проектов также можно изменить HintPath в project следующим образом:

<HintPath>$(SolutionDir)\packages\EntityFramework.6.1.0\lib\net40\EntityFramework.dll</HintPath>

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

Я думаю, что это лучшее решение, когда вы разветвляете код, при установке общего РЕПО вы должны изменить относительный путь, в этом решении вам не нужно это делать.


мой опыт пытается это сделать с последней версией NuGet (2.7) и VS2012:

  • удалить .папка nuget (на диске и в решении)
  • положите NuGet.Конфигурационный файл в общей родительской папке всех решений
  • удалить все существующие папки пакеты
  • пройдите через все файлы csproj и измените HintPaths, чтобы указать на новое местоположение
  • прибыль

в моем случае я хотел поместить все пакеты в .packages, Итак, мой NuGet.Конфигурация выглядела как ниже.

 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
   <config>
     <add key="repositorypath" value=".packages" />
   </config>
 </configuration>

обратите внимание, что есть несколько "странных" вещей, которые могут произойти, но я думаю, что они терпимы:

  • если вы "обновите" пакет из одного решения, он быстро удалит старую версию из папки "пакеты" (он не может знать, есть ли у вас другое решение, которое указывает туда). Это меня не сильно беспокоит, так как другое решение будет просто восстанавливаться при необходимости.
  • если вы пытаетесь добавить пакет из правой кнопки мыши на решении, если пакет уже присутствует в другом решении, он увидит, что он есть, и покажет вам "зеленую галочку" вместо кнопки "Установить". Обычно я устанавливаю из правой кнопки мыши по проекту, поэтому это меня совсем не беспокоит.

отказ от ответственности: я только что попробовал это сегодня, у меня нет долгосрочного опыта, чтобы поддержать его!


у меня есть версия NuGet 2.8.50926 с VS 2013. Вам не нужно использовать несколько nuget.конфигурационные файлы, или использовать сложные структуры каталогов. Просто измените файл по умолчанию находится здесь:

%APPDATA%\Roaming\NuGet\NuGet.Config

вот содержимое моего файла:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="repositoryPath" value="C:\Projects\nugetpackages" />
  </config>
  <activePackageSource>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  </activePackageSource>
</configuration>

поэтому все пакеты идут в "C:\Projects\nugetpackages-папка, где бы ни было решение.

во всех ваших решениях просто удалите существующие папки "пакеты". Затем создайте свое решение, и NuGet будет автоматическое восстановление отсутствующих пакетов в указанном вами новом централизованном каталоге.


уже нет необходимости изменять nuget.цели. Он был исправлен в nuget 2.8 (http://nuget.codeplex.com/workitem/2921). Вам нужно только установить repositorypath.


я состряпал пакет NuGet, который прозрачно преобразует все ссылки NuGet в проекте в относительный формат $(SolutionDir). Он делает это с помощью преобразования XSLT во время сборки, поэтому вам не нужно вручную взломать файл проекта. Вы можете свободно обновлять свои пакеты, это ничего не сломает.

https://www.nuget.org/packages/NugetRelativeRefs

или при использовании Visual Studio 2015 с обновлением 3 можно просто перенести ссылки на пакет project.json форма, как описано здесь: https://oren.коды/2016/02/08/project-json-все-вещи


обновление моего опыта работы с nuget 2.8.3. Все было относительно просто. Все сделал включено восстановление пакета от щелчка правой кнопкой мыши решение. Редактировать С Помощью NuGet.Config и добавил Эти строки :

  <config>
    <add key="repositorypath" value="..\Core\Packages" />
  </config>

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

Вот пошаговая процедура для включения восстановления пакета.

http://blogs.4ward.it/enable-nuget-package-restore-in-visual-studio-and-tfs-2012-rc-to-building-windows-8-metro-apps/


из Visual Studio 2013 Update 4 и версии диспетчера пакетов Nugget > 2.8.5...

создать nuget.файл config в корне репозитория.

файл содержимое:

<configuration>
  <config>
    <add key="repositoryPath" value="packages" />
  </config>
  <packageSources>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  </packageSources>
</configuration>

это приведет к тому, что все пакеты перейдут в папку packages на уровне вашего nuget.конфигурационный файл.

теперь вы можете пойти для каждого .консоль sln nuget с командой "update-package-reinstall"

Если у вас есть несколько репозиториев на одном уровне и что поделитесь одной и той же папкой пакета через них попробуйте использовать способ перехода на одну папку вверх.

 <add key="repositoryPath" value="..\packages" />

но таким образом вы вызываете, что ссылка на пакеты nuget csproj указывает одну папку вне пути репозитория.


просто hardlink / packages в нужное общее местоположение. Тогда ваш проект не будет разбит для других пользователей, у которых нет специального расположения пакетов.

Откройте командную строку как admin и используйте

mklink /prefix link_path Target_file/folder_path

для любого значимого решения вышеуказанные ответы не подойдут. Проще говоря, сложная структура рабочего пространства TFS с различными относительными путями, ветвлением, общими проектами и т. д. сделать единое центральное хранилище невозможным.

использование ($SolutionDir) является шагом в правильном направлении, но ручное кодирование файла csproj с помощью ($SolutionDir) станет довольно утомительным в базе кода с сотнями пакетов, которые регулярно обновляются (каждый раз, когда происходит обновление, HintPath получает перезаписано новым относительным путем). Что произойдет, если вам нужно запустить Update-Package-Reinstall.

есть отличное решение под названием NugetReferenceHintPathRewrite. Он автоматизирует инъекцию ($SolutionDir) в HintPaths непосредственно перед сборкой (без фактического изменения файла csproj). Я предполагаю, что он может быть легко включен в автоматизированные системы сборки


краткое резюме для тех, кто на VS 2013 professional С NuGet для версия: 2.8.60318.667

Это то, как вы направили бы пакеты на путь относительно .папка nuget:

<configuration>
  <config>
    <add key="repositoryPath" value="../Dependencies" />
  </config>
</configuration>

например, если решение (.sln-файл) находится в C:\Projects\MySolution, когда вы включаете восстановление пакета NuGet,.папка nuget создается следующим образом: C:\Projects\MySolution - ... NuGet и пакеты будут загружены в каталог вот так: C:\Projects\MySolution\Dependencies

Примечание: по какой-то (неизвестной) причине каждый раз, когда я обновляю "repositoryPath", я должен закрыть и снова открыть решение, чтобы изменения вступили в силу


для тех, кто использует пакет в качестве менеджера пакетов, есть опция автоматической символической ссылки для вашего файла зависимостей:

storage: symlink

btw: пакет использует nuget

ссылка:https://fsprojects.github.io/Paket/dependencies-file.html

Если вы хотите изменить как можно меньше, вы можете просто периодически очищать подкаталоги с помощью скрипта. то есть. Поведение Nuget по умолчанию-копирование файлов из глобального местоположения в локальные пакеты папка, поэтому удалите эти файлы позже.


Это инструкции по состоянию на NuGet 2.1: http://docs.nuget.org/docs/release-notes/nuget-2.1

нет необходимости редактировать файлы уровня решения.

работает с Visual Studio 2013 и тремя проектами совместного использования решений.

Не забудьте обновить NuGet уровня решения (каждый nuget.exe в .папки из NuGet).