CLI утилиты на C#: от идеи до готового инструмента за вечер

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему C# идеален для CLI-инструментов, и почему это важно для Python-разработчика

Когда мы говорим о создании консольных утилит, в голову первым делом приходят Python, Bash или Go. Но что, если я скажу вам, что C# — один из самых недооценённых языков для написания быстрых, кроссплатформенных и красивых CLI-инструментов? Да-да, тот самый C#, который многие ассоциируют с веб-формами и корпоративными монстрами.

С выходом .NET 6/8, C# обзавёлся минимальным API, нативной компиляцией (AOT) и невероятно удобной библиотекой System.CommandLine. Теперь создать утилиту, которая работает на Windows, Linux и macOS, можно буквально за 15 минут. Для студентов и разработчиков, изучающих Python, это отличный способ расширить инструментарий и понять, как устроены CLI-утилиты на других языках.

В этой статье мы не просто напишем "Hello World". Мы создадим полноценную утилиту для работы с файлами, которая умеет парсить аргументы, выводить цветной текст, обрабатывать ошибки и даже показывать прогресс-бар. Поехали!

Настройка проекта: минимум телодвижений

Первое, что нужно сделать — убедиться, что у вас установлен .NET SDK (версия 6.0 или выше). Проверить просто:

dotnet --version

Если всё ок, создаём новый консольный проект:

dotnet new console -n FileGuardian
cd FileGuardian

Уже на этом этапе мы получаем готовый скелет. Но для настоящей CLI-утилиты нам понадобится библиотека для парсинга аргументов. Добавляем её:

dotnet add package System.CommandLine --version 2.0.0-beta4.22272.1

Готово. Теперь у нас есть всё для создания профессионального консольного приложения на C#.

Почему System.CommandLine, а не ручной парсинг?

Многие новички пишут args[0], args[1] и ловят IndexOutOfRangeException. Это путь боли. System.CommandLine даёт:

  • Автоматический парсинг флагов (--output, -o)
  • Подсказки при неверном вводе
  • Встроенную генерацию --help
  • Поддержку подкоманд (как в git)

Это must-have для любой серьёзной консольной утилиты C#.

Пишем ядро утилиты: первая команда

Представьте, что мы создаём инструмент для мониторинга файлов — FileGuardian. Он будет проверять размер файлов и предупреждать, если они превышают лимит. Звучит полезно, правда?

Откроем Program.cs и напишем следующее:

using System.CommandLine;

var rootCommand = new RootCommand("FileGuardian — утилита для мониторинга файлов");

var fileOption = new Option<FileInfo?>(
    name: "--file",
    description: "Путь к файлу для анализа"
);
rootCommand.AddOption(fileOption);

rootCommand.SetHandler((file) =>
{
    if (file is null || !file.Exists)
    {
        Console.Error.WriteLine("❌ Файл не найден!");
        return;
    }
    
    long sizeInBytes = file.Length;
    double sizeInMb = sizeInBytes / (1024.0 * 1024.0);
    
    Console.WriteLine($"📄 Файл: {file.Name}");
    Console.WriteLine($"📏 Размер: {sizeInMb:F2} MB");
    
    if (sizeInMb > 100)
        Console.WriteLine("⚠️ Внимание: файл превышает 100 MB!");
}, fileOption);

await rootCommand.InvokeAsync(args);

Запускаем:

dotnet run -- --file somefile.txt

Уже работает. Но это только начало. Давайте добавим изюминку — цветной вывод и прогресс-бар.

Красивый вывод: добавляем цвета и эмодзи

Консоль не обязана быть чёрно-белой. C# позволяет легко менять цвета текста. Создадим вспомогательный класс:

public static class ConsoleHelper
{
    public static void WriteSuccess(string message)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"✅ {message}");
        Console.ResetColor();
    }
    
    public static void WriteError(string message)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"❌ {message}");
        Console.ResetColor();
    }
    
    public static void WriteWarning(string message)
    {
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine($"⚠️ {message}");
        Console.ResetColor();
    }
}

Теперь наш код обработки файла станет информативнее. Замените строки с Console.WriteLine на вызовы ConsoleHelper.WriteSuccess() и ConsoleHelper.WriteWarning(). Пользователь сразу увидит, всё ли в порядке.

Это превращает CLI-утилиту на C# в продукт, которым приятно пользоваться.

Продвинутый парсинг: подкоманды и несколько аргументов

Хорошая утилита должна уметь делать несколько вещей. Добавим вторую команду — поиск дубликатов файлов по размеру. Для этого используем подкоманды:

var checkCommand = new Command("check", "Проверить размер файла");
checkCommand.AddOption(fileOption);
checkCommand.SetHandler((file) => { /* код проверки */ }, fileOption);

var findCommand = new Command("find", "Найти дубликаты по размеру");
var directoryOption = new Option<DirectoryInfo?>(
    name: "--dir",
    description: "Директория для поиска"
);
findCommand.AddOption(directoryOption);
findCommand.SetHandler((dir) =>
{
    if (dir is null || !dir.Exists)
    {
        ConsoleHelper.WriteError("Директория не найдена");
        return;
    }
    
    var files = dir.GetFiles("*", SearchOption.AllDirectories);
    var groups = files.GroupBy(f => f.Length)
                      .Where(g => g.Count() > 1);
    
    foreach (var group in groups)
    {
        ConsoleHelper.WriteWarning($"Размер: {group.Key} байт");
        foreach (var file in group)
            Console.WriteLine($"  - {file.FullName}");
    }
}, directoryOption);

rootCommand.AddCommand(checkCommand);
rootCommand.AddCommand(findCommand);

Теперь наша утилита C# CLI поддерживает две команды:

  • dotnet run -- check --file data.txt
  • dotnet run -- find --dir ./documents

Выглядит как настоящий профессиональный инструмент, не правда ли?

Обработка ошибок: делаем утилиту надёжной

Одна из самых частых проблем начинающих — игнорирование исключений. Пользователь вводит неверный путь, и программа падает с StackTrace. Это убивает доверие. Давайте добавим централизованную обработку:

<                

Блоги

Рекомендаций по книгам