Andrey on .NET | Использование NuGet. Часть 1 – Управление библиотеками

Использование NuGet. Часть 1 – Управление библиотеками

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

А зачем NuGet нужен?

Как уже было отмечено, основной задачей NuGet является упрощение процесса установки сторонних библиотек. Он берет на себя все шаги этого процесса, в том числе:

  • поиск библиотеки;
  • загрузка необходимого для установки пакета;
  • проверка его хэш-значения на соответствие с заданным сервером (проверка целостности);
  • распаковка файлов библиотеки в нужное место;
  • добавление ссылок (reference) на её сборки в проект;
  • модификацию файлов конфигурации (web.config, app.config) при необходимости.

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

Установка NuGet

Installing NuGetЕсли на рабочей станции еще не был установлен NuGet, то его необходимо загрузить его с помощью менеджера дополнений Visual Studio. Для этого достаточно выбрать раздел Online Gallery и в строке поиска указать название "nuget". При этом поддерживаются все версии среды разработки – от Express  до Ultimate.

Официальный сайт проекта: https://www.nuget.org/

Использование NuGet

Графический интерфейс "Add Library Package Reference"

Для наглядности давайте создадим новый проект. Пусть это будет обычное консольное приложение. Попробуем добавить в него библиотеку Castle.DynamicProxy, предназначенную для создания во время выполнения динамических Прокси. Кстати, использование этой библиотеки уже рассматривалось при создании динамического Декоратора.

Откроем контекстное меню проекта Solution Explorer или Solution Navigator и выберем пункт "Add Library Package Reference". В открывшемся диалоговом окне перейдем раздел "Online". Обратите внимание, что в данный момент два типа источника библиотек – все (All) и официальные (NuGet official package source). В строке поиска укажем "Castle", немного подождем и посмотрим на появившиеся результаты:

Searching for the library

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

Выберем библиотеку Castle.DynamicProxy и нажмем кнопку "Install". Произойдет установка выбранного компонента. Давайте посмотрим, что добавилось в созданный проект.

В первую очередь это сама библиотека Castle.DynamicProxy. Её легко можно заметить в списке References проекта. Кроме того, её инсталляционный пакет указал зависимости от другой библиотеки: Castle.Core. А она, в свою очередь, потребовала наличия log4net и NLog. В результате все эти компоненты были найдены и установлены.

Обратите внимание, что могут быть указаны зависимости различных видов. Здесь их два:

  • В первом случае требуется определенная версия библиотеки. В частности при установке была затребована именно Castle.Core 1.2.0. И не смотря на то, что на данный момент уже доступна 2 версия, она установлена не будет. Причем, даже если потом попытаться установить новую версию самостоятельно, то будет выведено сообщение об ошибке.
  • Во втором случае указывается минимальная версия, которая будет загружена. Но в дальнейшем возможно обновление до последней версии. Например, таким образом в данном примере были зависимости Castle.Core от log4net и NLog.

Где разместились загруженные файлы? NuGet создал в папке решения (solution) свою папку packages. По сути, это небольшой репозиторий проекта. Внутри него расположились DLL и остальные файлы загруженных библиотек. Причем структура размещения внутри каждой папки частично определятся требованиями NuGet, а частично самим установленным компонентом.

Кроме того, в проект добавился один файл "packages.config", который в данный момент выглядит так:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="log4net" version="1.2.10" />
  <package id="NLog" version="1.0.0.505" />
  <package id="Castle.Core" version="1.2.0" />
  <package id="Castle.DynamicProxy" version="2.2.0" />
</packages>

Как легко можно понять, он описывает добавленные в текущий проект библиотеки.

Давайте вновь откроем диалоговое окно "Add Library Package Reference" и перейдем в раздел "Updates". NuGet при этом проверит доступные обновления для установленных библиотек. В результате будет выведен список, какие из них обновились.

Getting updates

Попытка обновить Castle.Core приведет к неудаче. Как уже было отмечено, Castle.DynamicProxy требует определенную её версию. А вот NLog можно обновить, нажав кнопку "Update".

После обновления перейдем обратно в раздел Installed Packeges. В нем приведен список всех установленных компонентов. Кроме того, здесь можно убедиться что NLog был обновлен и его описание содержит номер последней версии (на момент создания данной статьи это 2.0.0.0):

Installed packages

При выборе любой из приведенных в списке библиотек, рядом появляется кнопка "Uninstall". Однако, удалить возможно только те, от которых не зависят другие компоненты. Для остальных будет показано сообщение об ошибке. Таким образом NuGet следит за соблюдением зависимостей.

Давайте сейчас удалим добавленные компоненты. Порядок при этом будет такой: вначале Castle.DynamicProxy, затем Castle.Core и последними будут удалены log4net и NLog. Обратите внимание, что были удалены не только ссылки на сборки (References), но и загруженные установочные пакеты.

Консоль "Package Manager Console"

Посмотрим на еще один способ работы с NuGet. Он подойдет тем, кому больше нравится работать с командной строкой, чем с диалоговыми окнами. Сразу необходимо отметить, что поддерживается подсказка для завершения набора команд. Для её активации необходимо ввести несколько первых букв и нажать кнопку "Tab".

Откроем Package Manager Console с помощью меню View > Other Windows (другой вариант – Tools > Library Package Manager). После загрузки и инициализации PowerShell, который она использует, оно выглядит следующим образом:

NuGet Package Manager Console

Давайте сначала посмотрим как найти нужную библиотеку в этом случае. Для этого необходимо дать команду "Get-Package -ListAvailable". Однако в этом случае будет выведен огромный список всех доступных установочных пакетов. Поэтому уточним команду, добавив строку для поиска. В итоге поучится следующий вариант: "Get-Package -ListAvailable castle.dynamic". Результатом его работы будет список доступных библиотек, в имени или описании которых есть указанная строка.

Searching for the project in NuGet Package Manager Console

Добавим найденную библиотеку в проект. Для этого укажем следующую команду: "Install-Package Castle.DynamicProxy". Результат её выполнения будет аналогичным использованию диалога "Add Library Package Reference".

Как и в примере с графическим интерфейсом, теперь попробуем обновить библиотеки. Чтобы узнать какие новые версии доступны необходимо ввести команду "Get-Package -updates". Посмотрим на полученный список и решим, также как и в прошлый раз, обновить NLog. Укажем следующую команду: "Update-Package NLog", которая приведет к загрузке и установке последней версии этого компонента.

Остается рассмотреть как удалить установленную библиотеку. Для этого используется команда "Uninstall-Package". Давайте введем "Uninstall-Package Castle.DynamicProxy" в командной строке консоли. После чего при помощи команды "Get-Package" без параметров вызовем список установленных пакетов и убедимся что Castle.DynamicProxy был действительно удален. Аналогично, с помощью команды Uninstall-Package удалим оставшиеся пакеты.

Использования консоли для операций над группой проектов (конвейер команд)

Необходимо отметить еще одну возможность, которая предоставляет "Package Manager Console". Это возможность объединения команд в "конвейер" (pipeline). В частности это позволяет выбрать проект, к которому будет применена следующая команда. Для этого в начале строки необходимо указать:

  1. Get-Project –All – чтобы выбрать все проекты текущего решения (solution).
  2. Get-Project –Name projectName -  чтобы выбрать проект с именем projectName.

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

  • Установка: Get-Project -All | Install-Package [params]
  • Обновление: Get-Project -All | Update-Package [params]
  • Удаление: Get-Project -All | Uninstall-Package [params]

Если необходимо выборочно обновлять несколько проектов, можно написать скрипт для PowerShell. Для этого необходимо создать файл с расширением .ps1. Например, пусть это будет update.ps1 в папке, являющейся корнем решения. В нем будут заданы команды для обновления библиотек c указанием проектов:

Update-Package Castle.Core -ProjectName projectName1
Update-Package Castle.Core -ProjectName projectName3
Update-Package Castle.Core -ProjectName projectName4

В дальнейшем, запустить данный скрипт на выполнение можно указав путь до него и его имя. При этом сам путь задается относительно корневой папки проекта и начинается c ".\". Например, ".\update.ps1". Аналогично можно задать любую последовательность действий для NuGet.

Настройки NuGet

Начиная с версии 2.1 NuGet позволяет управлять несколькими полезными настройками с помощью файлов NuGet.config.

Иерархия NuGet.config

Для определения настроек, специфичных для конкретной папки и вложенных в неё папок, необходимо разместить в ней файл NuGet.config с новыми параметрами.

Это может использоваться для задания источников, специфичных для определенных проектов. Например, разместим в папке C:\MyProjectGroup1 файл NuGet.config, который добавляет новый источник:

<configuration>
  <packageSources>
    <add key="My source" value="http://myserver/api/v2/" />
  </packageSources>
  <disabledPackageSources />
  <activePackageSource>
    <add key="My source" value="http://myserver/api/v2/" />
  </activePackageSource>
</configuration>

Теперь My source доступен всем проектам внутри C:\MyProjectGroup1, но не доступен остальным.

Указание места размещения установочных пакетов

При большом числе решений, на диске скапливается множество копий одних и тех же установочных пактов. Это можно исправить, указав в файле NuGet.config единое место для размещения:

<configuration>
  <config>
    <add key="repositoryPath" value="C:\MyProjectGroup1\TeamPackages" />
  </config>
  ... 
</configuration>

Если указанную строку добавить в файл из примера выше, то все проектам внутри C:\MyProjectGroup1 будут хранить свои установочные пакеты в папке C:\MyProjectGroup1\TeamPackages. Стоит отметить, что можно указывать относительные пути.

Список доступных консольных команд NuGet

Стоит еще раз отметить, что в консоли NuGet поддерживается подсказка по нажатию кнопки "Tab". Это очень сильно ускоряет процесс работы с ней и делает её в чем-то даже удобнее и быстрее варианта с графическим интерфейсом. Причем, подсказка есть не только для имен самих команд, но и параметров и их значений. При этом если существует только один вариант, то он будет сразу вставлен в текст команды.

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

Другой пример – указание имени проекта. Это необходимо в случае, если в решении (solution) их содержится несколько. В этом случае, после параметра команды также можно нажать кнопку "Tab". В окне подсказки будут перечислены все доступные проекты.

Давайте теперь перейдем к списку команд, доступных в консоли NuGet.

Get-Package – вывод списка установочных
[Без параметров] Выводит список установленных пакетов.
‑ProjectName projectName Отображает список пакетов, установленных в указанном в качестве параметра проекте projectName.
‑Source sourceUrlOrPath Определяет источник для получения информации о пакетах. Это может быть RSS поток, папка на диске или сервис, поддерживающий OData.
-ListAvailable [filterSpecification] Выводит список библиотек, доступных в выбранном источнике. Возможна установка фильтра, который применяется для названий и описаний библиотек.
‑Updates Отображает список библиотек, для которых доступны обновления.
‑Recent Выводит список последних установленных библиотек.
‑First N Отображает первые N установочных пакетов в списке.
‑Skip N Пропускает N установочных пакетов при выводе списка. Вместе с параметром –First позволят выводить список частями. Например, чтобы вывести названия библиотек с 15 по 45 необходимо указать "–Skip 15 –First 30"
‑Filter filterSpecification Устанавливает фильтр для вывода списка библиотек как установленных, так и на доступных в источнике. Применяется к названию и описанию библиотеки.
Install‑Package – установка библиотек

‑Id packageName

Обязательный первый параметр (при этом можно опустить "–Id"). Задает имя установочно пакета. При этом если не ввести имя показывается 30 самых библиотек с самым большим рейтингом. Если указать часть имени, то осуществляется поиск по вхождению указанного текста в имена библиотек.
‑IgnoreDependencies Указывает необходимость установки только указанной библиотеки, игнорируя её зависимости от других.
‑Project projectName Определяет в какой из проектов необходимо установить библиотеку. По умолчанию используется проект текущий проект, указанный в окне консоли.
‑Source sourceURL Указывает источник получения установочного пакета.
‑Version versionNumber Запрашивает установку указанной версии библиотеки (по умолчанию используется самая последняя).
‑FileConflictAction action Определяет действие, если устанавливаемый файл уже существует в проекте. Параметр action может принимать одно из значений: Overwrite (перезаписать) или Ignore (пропустить).
Uninstall‑Package – деинсталляция библиотек

‑Id packageName

Обязательный первый параметр (при этом можно опустить "–Id"). Определяет имя библиотеки для удаления.
‑RemoveDependencies Указывать не необходимость так же удалить пакеты, от которых зависит библиотека и которые не используются другими.
‑Force Удаляет библиотеку, даже если есть зависимые от неё компоненты.
‑Version versionNumber Указывает версию удаляемой библиотеки. По умолчанию выбирается самая последняя версия.
‑Project projectName Определяет из какого проекта удаляется библиотека. По умолчанию используется проект текущий проект, указанный в окне консоли.
Update-Package – обновление установленных библиотек

‑Id packageName

Первый параметр (при этом можно опустить "–Id"). Определяет имя библиотеки, для которой производится поиск и установка обновления. Если он не указан, то производится обновление всех библиотек.
‑Reinstall Указывает на необходимость переустановки библиотеки. Установочный пакет удаляется, загружается повторно и устанавливается в заданный проект.
‑UpdateDependencies При установке этого флага производится обновление всех зависимых библиотек.
‑ProjectName projectName Определяет в каком проекте будет обновлены библиотеки. Если ключ не указан, то выбранный пакет или все пакеты обновляются во всех проектах решения.
‑Source sourceURL Переопределяет источник получения установочного пакета для данной команды.
‑Version versionNumber Указывает версию до которой происходит обновление. По умолчанию выбирается самая последняя версия.
‑Safe Задействует безопасное обновление, т.е. загружаются только минорные обновления. Например: установлена версия 1.0.0 и доступны 1.0.1, 1.0.2 и 1.1. При использовании ключа –safe будет загружена версия 1.0.2, а без него – 1.1.
Open-PackagePage – переход на страницу проекта

‑Id packageName

Обязательный первый параметр (при этом можно опустить "–Id"). Определяет имя библиотеки, страница которой будет открыта в браузере.
‑Version versionNumber Указывает номер версии.
‑Source sourceURL Переопределяет источник получения установочного пакета для данной команды.
‑License Открывает в браузере страницу с лицензионным соглашением.
‑ReportAbuse Открывает в браузере страницу для подачи жалобы.
‑PassThru

Изменяет поведение команды. Вместо открытия браузера возвращается строка с адресом выбранной страницы. Например, следующий код присваивает переменной $url ссылку на страницу с текстом лицензии:
$url = Open-PackagePage Ninject -License -WhatIf -PassThru

Get–Projects  - выбор проекта(ов) (для конвейера команд)
[Без параметров] Возвращает текущий проект.

-All

Возвращает все проекты загруженного решения (solution).
‑Name projectName Возвращает заданный проект для команды.

 

 

В завершении несколько примеров:

  • Get-Package -ListAvailable Razor – выводит список всех доступных установочных пакетов, у которых в имени или описании есть текст "Razor".
  • Get-Package –ListAvailable -Skip 5 -First 10 Castle – отображает перечень с 5 по 15 библиотеку, в названии которых содержится слово "Castle".
  • Get-Package -Update -Filter Castle – отображает список обновлений, доступных для установленных проектов в названии которых содержится слово "Castle".
  • Update-Package – обновляет все установочные пакеты во всех проектах текущего решения.
  • Update-Package EntityFramework – обновляет пакет EntityFramework во всех проектах решения.
  • Update-Package –ProjectName MVCDemo – обновляет все пакеты в проекте MVCDemo.
  • Install-Package Raz[нажатие кнопки "Tab"] – откроет окно подсказки с списком библиотек, имена которых начинаются с текста "Raz". Обратите внимание на возможность пропускать указание "–Id".

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

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

Комментарии (9) -

А как вы решили проблемы апдейта библиотек во всех проектах солюшена?
К примеру у меня около 15 проектов. В 8ми из них есть библиотека, которую нужно обновить. Клацать каждую - не вариант.

Если для всех, то можно вот так:

Get-Project -All | Update-Package Castle.Core

Библиотека будет обновлена в тех проектах, где она установлена.
Добавил в статью данный способ.

Andrey :
Если для всех, то можно вот так:
1
Get-Project -All | Update-Package Castle.Core

Библиотека будет обновлена в тех проектах, где она установлена.
Добавил в статью данный способ.

Не работает так, по крайней мере не работало неделю назад. Если нет референса в проекте, то NuGet ругается и апдейт обрывается.

Проверял на тестовом решении и не заметил что библиотека есть во всех проектах. Попробовал создать с нуля и действительно ругается.

В этом случае остается только написать powershell script с строками типа:
Get-Project Project1 | Update-Package Castle.Core
Get-Project Project3 | Update-Package Castle.Core

Или сразу
Update-Package Castle.Core ‑ProjectName Project1
Update-Package Castle.Core ‑ProjectName Project3
и т.д.

@ Andrey:

Я лучше подожду новой версии NuGet где эта проблема решена Laughing

essay writing service 18.01.2012 15:56:23

Спасибо, очень интересно.

О боже, это одна из самых благодатных блогозаписей на тему NuGet!!!
Огромное спасибо! Блогослови автора Бог и РПЦ! Laughing

Кстати, путь к каталогу с установлеными пакетами может быть относительным и это работает, пример:


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


Что очень удобно, однако!

Таким скриптом можно обновить package во всех проектах:
Get-Project -All | ?{ (Get-Package Castle.Core -ProjectName $_.ProjectName) -ne $null } | Update-Package Castle.Core

@AlgeG посмотрите в сторону Manage NuGet Packages for solution... -> Consolidate docs.microsoft.com/.../install-use-packages-visual-studio

Pingbacks and trackbacks (1)+

Добавить комментарий