Пару недель назад вышел .NET Core 2.1 RC1. Это первая версия SDK, где есть фича под названием "Глобальные утилиты .NET Core" (".NET Core Global Tools"). Она дает простой способ создания кросс-платформенных консольных утилит.  Мы познакомимся с основами использования .NET Core Global Tools и кратко посмотрим, что внутри. А еще вы можете скачать .NET Core 2.1 SDK и попробовать написать собственный пример. .NET Core global tool — это специальный пакет NuGet, в котором находится консольное приложение. Когда вы устанавливаете его, .NET Core CLI скачивает пакет и делает его доступным в виде новой глобальной консольной команды. Пользователи могут устанавливать утилиты с помощью команды dotnet tool install: После установки консольные утилиты, находящиеся в пакете, будут глобально доступны по имени: dotnet tool имеет и другие команды. Например: NuGet пакет с консольной утилитой содержит все файлы, полученные в результате выполнения команды dotnet publish, а также несколько дополнительных файлов с мета-информацией. Когда вы запускаете dotnet tool install --global, происходит следующее: Сгенерированный запускаемый файл — это небольшое консольное приложение (написанное на C++), которое знает, где находится ваш .NET Core DLL файл и автоматически запускает его. Вы также можете запустить dotnet tool install с аргументом --tool-path $installDir. Эта команда делает всё то же самое, но устанавливает консольное приложение в папку $installDir, а не в $HOME/.dotnet/tools. Для создания глобальных консольных утилит вам нужен .NET Core SDK версии 2.1. В этой версии добавлено несколько дополнительных настроек проектов для управления неймингом и содержимым пакетов с глобальными консольными утилитами. Минимальные необходимые параметры проекта: Дополнительные (не обязательные) параметры, управляющие сборкой пакета: Пример использования этих параметров: Сборка пакета происходит как обычно — при помощи команды dotnet pack. SDK увидит, что установлен параметр PackAsTool=true и автоматически сгенерирует нужные дополнительные файлы. С помощью параметра --source-feed вы можете установить пакет, который еще не опубликован в репозитории пакетов NuGet. Это может быть полезно для проверки, что всё сделано правильно. Также, если версия пакета — не релизная (например, 3.0.0-alpha — содержит что-то, кроме трех чисел), нужно при установке явно указать её. Например: Как я писал выше, команда dotnet pack собирает пакет особым образом, если в файле проекта указан параметр PackAsTool=true. В пакет попадают не только файлы, полученные через dotnet build, но и все другие зависимости вашего проекта (подключенные сторонние пакеты NuGet). Все файлы, необходимые для работы вашей консольной утилиты, должны быть включены в NuGet пакет. Команда dotnet-tool-install не устанавливает зависимости, указанные в резделе <dependencies> вашего .nuspec файла. Генерируется специальный файл DotnetToolSettings.xml, который содержит информацию о вашем консольном приложении. Если этого файла по какой-то причине не окажется в пакете (например, пытаетесь установить произвольный пакет как консольную утилиту), то при установке вы получите ошибку: Пример содержимого файла: Сейчас есть следующие требования к файлу DotnetToolSettings.xml: В .nuspec файл автоматически добавляется параметр <packageType name="DotnetTool" />. Например: Если параметр packageType[name] не указан как DotnetTool, то при установке получите ошибку: Конечно, это не очень понятное сообщение об ошибке. На Github есть issue, чтобы это улучшить. .NET Core CLI по умолчанию устанавливает глобальные утилиты в папку $HOME/.dotnet/tools (на Linux/macOS) или в папку %USERPROFILE%\.dotnet\tools (на Windows). Это значит, что вы не можете установить пакет глобально для всех пользователей компьютера с помощью dotnet tool install --global. Установленные утилиты доступны только для пользователя, который их установил. Обычно .NET Core автоматически добавляет путь к папке с установленными утилитами в переменную окружения PATH, чтобы они были доступны по имени, без указания полного пути. Но иногда это может не сработать. Например: В этом случае при запуске своей консолььной утилиты вы получите ошибку. Например: Чтобы всё заработало, нужно добавить в переменную PATH путь к папке с утилитами. Например так (после добавления нужно перезапустить терминал): Или вот так можно добавить для текущей сессии: Примеры выше — для MacOS. Для других систем всё аналогично. Кроме того, при установке вашей глобальной консольной утилиты команда dotnet tool install проверит, что переменная PATH правильно настроена и предложит варианты решения, если это не так. Если вы скачали .NET Core CLI как .zip/.tar.gz архив и распаковали его в папку, которая отличается от папки по умолчанию, то при запуске своей консольной утилиты вы можете получить ошибку: В сообщении об ошибке будет также дополнительная информация: Причина в том, что запускаемы файл, который генерируется командой dotnet tool install при установке пакета, ищет .NET Core в папке по умолчанию. Вы можете переопределить пути по умолчанию, установив переменную окружения DOTNET_ROOT. Например: Подробности в issue на GitHub. Мы познакомились с глобальными консольными утилитами в .NET Core. На мой взгляд, это очень крутая штука. Я крайне счастлив, что команда .NET Core её запилила. Не могу дождаться, когда все начнут её использовать :)