Мы использовали довольно много инструментов интерфейса командной строки (CLI) .NET Core, таких как dotnet new, dotnet build, dotnet add package, dotnet watch run, dotnet ef database update и так далее. Вы когда-нибудь задумывались о создании подобного собственного инструмента интерфейса командной строки?

В мире .NET Core эти инструменты называются Global Tools (ссылка). .NET Core Global Tool - это специальный пакет NuGet, содержащий консольное приложение, которое можно вызывать в терминале с помощью предопределенных команд в Global Tool.

Говоря о программе CLI в .NET, можно сразу рассмотреть консольные приложения (ссылка) и приложения PowerShell (бинарные модули PowerShell (ссылка) и командлеты PowerShell (ссылка)). Давайте сначала кратко поговорим о них.

Приложения PowerShell просты в использовании, поскольку командная строка дает подсказки о доступных командах, подкомандах и параметрах в терминале PowerShell и / или PowerShell ISE. PowerShell также поддерживает сценарии с управлением Windows (ссылка), преобразование данных, конвейеры (ссылка) и так далее. Мы можем создавать наши программы CLI на C # и интегрировать их со сценариями PowerShell, которые используются для управления компьютерными системами или обработки данных. Однако, несмотря на все эти плюсы в PowerShell, приложения PowerShell на C # возникли на короткое время, а затем вымерли на моем рабочем месте, потому что процесс отладки был неприятным. В настоящее время все задачи системного администрирования и обработки данных предпочтительно пишутся на чистых сценариях PowerShell.

С другой стороны, консольные приложения легко отлаживать и тестировать, хотя анализ аргументов командной строки не так хорош, как в PowerShell. Хорошая новость заключается в том, что .NET разрабатывает набор собственных API-интерфейсов командной строки в пространстве имен System.CommandLine (ссылка). Кроме того, с появлением .NET Core 2.1 мы можем публиковать наши приложения как автономные приложения (ссылка), так что консольное приложение действительно может быть создано один раз и выполнено кросс-платформенным, не беспокоясь об операционных системах и .NET Core. версии. Более того, с выпуском .NET Core 3.0 мы можем публиковать наши приложения .NET Core как однофайловые исполняемые файлы (ссылка), так что консольное приложение может быть объединено как один исполняемый файл, что улучшает развертывание и использование. опыты.

Пользовательские глобальные инструменты впервые были поддержаны в .NET Core 2.1 (ссылка). Модель Global Tool - это, по сути, еще один метод публикации для консольных приложений, который упаковывает консольное приложение как пакет NuGet. После установки пакета NuGet глобально или локально один исполняемый файл извлекается и готов к вызову в командной строке.

Выполнение Global Tools требует знания интерфейса командной строки, а Global Tools требует их совместимой среды выполнения .NET Core. Если в текущей среде нет версии среды выполнения .NET Core, на которую нацелен Global Tool, инструмент может выдать ошибку. Таким образом, у Global Tools не так много реальных вариантов использования, и использование Global Tools в основном ограничено разработчиками.

Реальное преимущество выпуска Global Tool вместо обычного консольного приложения заключается в доступности Global Tool по общему реестру пакетов. Например, в конвейере CI / CD мы можем установить Global Tools по запросу, чтобы помочь нам выполнять некоторую обработку данных или манипулирование файлами в рабочем процессе.

OK. Хватит разговоров. Давайте создадим домашний проект, чтобы получить общее представление о создании и публикации Global Tool. Полное решение можно найти в этом репозитории GitHub.

Создание глобального инструмента

Официальная документация (ссылка) в Microsoft Docs очень хорошо объясняет процесс создания глобального инструмента. В основном процесс выглядит следующим образом.

  1. Создайте консольный проект и добавьте код.
    Этот шаг включает в себя все, что мы обычно делаем для создания консольного приложения. Например, добавьте синтаксический анализатор командной строки, добавьте несколько модульных тестов и так далее.
  2. Настройте глобальный инструмент
    . Это самый важный шаг, но он очень простой. Нам нужно только обновить *.csproj файл проекта консоли. В следующем фрагменте кода показан пример csproj файла для глобального инструмента.

В файле csproj строки с 6 по 9 - это настройки для глобального инструмента. Среди них требуется строка 6, которая сообщает системе сборки .NET, что проект нужно упаковать как Global Tool. Остальные строки (7, 8, 9) необязательны, и мы перезаписываем их значения по умолчанию в этом csproj файле. В строке 7 свойство ToolCommandName определяет имя команды, которая будет использоваться для вызова инструмента. Свойство PackageId определяет имя файла выходного пакета NuGet. Значения по умолчанию для PackageId и ToolCommandName - это имя проекта. В строке 9 PackageOutputPath - это каталог выпуска пакета NuGet. По умолчанию файл *.nupkg сохраняется в выходной каталог в папке bin. Здесь мы используем папку .nuget, чтобы легче было найти выходной пакет NuGet.

3. Создайте пакет NuGet на основе нашего приложения

dotnet pack

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

Результатом этой команды является *.nupkg файл в предварительно определенном каталоге вывода. С помощью этого файла пакета NuGet мы можем опубликовать его в nuget.org или других реестрах пакетов, чтобы пакет был доступен в общей сети.

Установить / обновить / удалить глобальный инструмент

Global Tool может быть установлен на нашем компьютере либо в месте по умолчанию, которое указано в переменной среды PATH, либо в произвольном месте. Мы можем использовать следующие команды, в зависимости от того, хотим ли мы вызвать инструмент в любом месте (глобально) или нет. Примечание. Если мы устанавливаем инструмент глобально, нам нужно быть осторожными с проблемой коллизии имен.

# install the tool to a default location
dotnet tool install --global --add-source .nuget stat 
# install the tool to a custom location
dotnet tool install --add-source .nuget stat --tool-path .\tools

Флаг «--add-source» позволяет dotnet tool системе узнать, где найти пакет NuGet. По умолчанию источником NuGet является nuget.org, который можно изменить на любой доступный источник. Здесь, в этом проекте, мы не будем публиковать этот игрушечный пакет, поэтому мы устанавливаем источник пакета NuGet в папку вывода файла *.nupkg. Кстати, это обычная практика - протестировать инструмент локально перед публикацией.

После установки инструмента мы можем вводить команды в терминале для использования инструмента. В приведенном ниже фрагменте показаны некоторые примеры (stat - имя команды глобального инструмента).

# if the tool is installed globally (Windows)
stat sd  -n 1 2 3
# the tool is installed to .\tools\ folder
.\tools\stat.exe sd  -n 1 2 3

Если доступна новая версия Global Tool, мы можем обновить этот инструмент с помощью команды dotnet tool update следующим образом.

dotnet tool update --global --add-source .nuget stat
dotnet tool update --add-source .nuget stat --tool-path .\tools

Наконец, мы можем удалить Global Tool, используя следующую команду.

dotnet tool uninstall -g stat

Или, если инструмент установлен в произвольном месте, мы можем напрямую удалить папку, чтобы удалить его. Мы всегда можем найти все текущие инструменты в системе, используя команду dotnet tool list, чтобы убедиться, что у нас есть правильный список инструментов.

В моем репозитории я сделал демонстрационный инструмент Global Tool, stat, который может выполнять простые вычисления для средних арифметических и стандартных отклонений массива чисел. В проекте есть файл Docker, который позволяет запускать Global Tool в контейнере докера. В следующей записи экрана показано, как создать образ докера и запустить его в контейнере Linux с .NET Core.

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

Это все на сегодня. Спасибо за прочтение.