SolimusWrapper 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package SolimusWrapper --version 1.0.0
                    
NuGet\Install-Package SolimusWrapper -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SolimusWrapper" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SolimusWrapper" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="SolimusWrapper" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SolimusWrapper --version 1.0.0
                    
#r "nuget: SolimusWrapper, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SolimusWrapper@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SolimusWrapper&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=SolimusWrapper&version=1.0.0
                    
Install as a Cake Tool

SolimusWrapper

NuGet License .NET Build

Лёгкая и оптимизированная библиотека для работы с CLI процессами в .NET. Простой и интуитивный API для запуска внешних команд с поддержкой перенаправления потоков, таймаутов, отмены и кросс-платформенной работы.

🚀 Особенности

  • Fluent API — читаемый и удобный синтаксис
  • Immutable — каждый вызов создаёт новый экземпляр команды
  • Асинхронность — полная поддержка async/await и CancellationToken
  • Перенаправление потоков — stdout, stderr, stdin
  • Таймауты — автоматическое завершение процессов
  • Кросс-платформенность — Windows, Linux, macOS
  • Оптимизация памяти — использование ArrayPool, ValueTask
  • Native AOT — поддержка trimming
  • Zero Dependencies — никаких внешних зависимостей

📁 Структура проекта

SolimusWrapper/
├── README.md                              # Главная документация
├── LICENSE                                # MIT License
├── SolimusWrapper.sln                       # Solution файл
│
├── src/
│   └── SolimusWrapper.Core/                      # 📦 Основная библиотека
│       ├── README.md
│       ├── SolimusWrapper.Core.csproj
│       ├── Command.cs
│       ├── CommandResult.cs
│       ├── CommandExtensions.cs
│       ├── PipeTarget.cs
│       ├── PipeSource.cs
│       ├── Optional.cs
│       └── Builders/
│           └── CommandBuilder.cs
│
├── samples/
│   └── SolimusWrapper.Demo/                 # 🎮 Примеры использования
│       ├── README.md
│       ├── SolimusWrapper.Demo.csproj
│       └── Program.cs
│
└── tests/
    └── SolimusWrapper.Tests/                # 🧪 Unit-тесты
        ├── README.md
        ├── SolimusWrapper.Tests.csproj
        ├── CommandTests.cs
        ├── CommandBuilderTests.cs
        ├── CommandResultTests.cs
        ├── PipeTargetTests.cs
        ├── PipeSourceTests.cs
        └── Fixtures/
            └── TestHelper.cs
Проект Тип Описание
SolimusWrapper.Core Class Library Ядро библиотеки (NuGet пакет)
SolimusWrapper.Demo Console App Примеры использования
SolimusWrapper.Tests xUnit Tests Unit-тесты

📦 Установка

dotnet add package SolimusWrapper

Или через Package Manager:

Install-Package SolimusWrapper

🎯 Быстрый старт

using SolimusWrapper;

// Простой запуск команды
var result = await Command.Run("dotnet")
    .WithArguments("--version")
    .ExecuteAsync();

Console.WriteLine($"Exit code: {result.ExitCode}");

// Получить вывод команды
var output = await Command.Run("git")
    .WithArguments("status")
    .ExecuteAndReadOutputAsync();

Console.WriteLine(output);

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

Базовые операции

// Запуск с аргументами
await Command.Run("dotnet")
    .WithArguments("build", "-c", "Release")
    .ExecuteAsync();

// Аргументы как коллекция
var args = new[] { "test", "--no-build", "--logger", "console" };
await Command.Run("dotnet")
    .WithArguments(args)
    .ExecuteAsync();

Получение вывода

// Только stdout
var stdout = await Command.Run("echo")
    .WithArguments("Hello, World!")
    .ExecuteAndReadOutputAsync();

// stdout и stderr отдельно
var (stdOut, stdErr) = await Command.Run("dotnet")
    .WithArguments("build")
    .ExecuteAndReadAllAsync();

Перенаправление потоков

var output = new StringBuilder();
var errors = new StringBuilder();

await Command.Run("dotnet")
    .WithArguments("build")
    .WithStandardOutputPipe(PipeTarget.ToStringBuilder(output))
    .WithStandardErrorPipe(PipeTarget.ToStringBuilder(errors))
    .ExecuteAsync();

Вывод в реальном времени

await Command.Run("dotnet")
    .WithArguments("test")
    .WithStandardOutputPipe(PipeTarget.ToDelegate(line => 
        Console.WriteLine($"[OUT] {line}")))
    .WithStandardErrorPipe(PipeTarget.ToDelegate(line => 
        Console.WriteLine($"[ERR] {line}")))
    .ExecuteAsync();

Запись в файл

await Command.Run("dotnet")
    .WithArguments("build", "-v", "detailed")
    .WithStandardOutputPipe(PipeTarget.ToFile("build.log"))
    .ExecuteAsync();

Передача данных в stdin

// Из строки
await Command.Run("grep")
    .WithArguments("error")
    .WithStandardInputPipe(PipeSource.FromString("line1\nerror here\nline3"))
    .ExecuteAsync();

// Из файла
await Command.Run("cat")
    .WithStandardInputPipe(PipeSource.FromFile("input.txt"))
    .ExecuteAsync();

// Из потока
using var stream = File.OpenRead("data.bin");
await Command.Run("processor")
    .WithStandardInputPipe(PipeSource.FromStream(stream))
    .ExecuteAsync();

Рабочая директория

await Command.Run("npm")
    .WithArguments("install")
    .WithWorkingDirectory("/path/to/project")
    .ExecuteAsync();

Переменные окружения

await Command.Run("node")
    .WithArguments("app.js")
    .WithEnvironmentVariable("NODE_ENV", "production")
    .WithEnvironmentVariable("PORT", "3000")
    .ExecuteAsync();

// Несколько переменных сразу
var envVars = new Dictionary
{
    ["API_KEY"] = "secret",
    ["DEBUG"] = "true"
};

await Command.Run("myapp")
    .WithEnvironmentVariables(envVars)
    .ExecuteAsync();

Таймауты

try
{
    await Command.Run("long-process")
        .WithTimeout(TimeSpan.FromSeconds(30))
        .ExecuteAsync();
}
catch (TimeoutException)
{
    Console.WriteLine("Процесс превысил лимит времени");
}

Отмена операции

using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));

try
{
    await Command.Run("long-task")
        .ExecuteAsync(cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Операция отменена");
}

Обработка кодов выхода

// По умолчанию выбрасывает исключение при ненулевом коде
try
{
    await Command.Run("failing-command").ExecuteAsync();
}
catch (CommandExecutionException ex)
{
    Console.WriteLine($"Команда завершилась с кодом: {ex.ExitCode}");
}

// Отключить проверку
var result = await Command.Run("might-fail")
    .WithValidation(false)
    .ExecuteAsync();

if (!result.IsSuccess)
{
    Console.WriteLine($"Exit code: {result.ExitCode}");
}

Callback при завершении

await Command.Run("task")
    .OnExit(exitCode => 
    {
        if (exitCode != 0)
            Console.WriteLine($"Warning: exit code {exitCode}");
    })
    .WithValidation(false)
    .ExecuteAsync();

Кодировка

using System.Text;

// Для Windows консоли (кириллица)
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

await Command.Run("cmd")
    .WithArguments("/c", "dir")
    .WithEncoding(Encoding.GetEncoding(866))
    .ExecuteAsync();

🔨 CommandBuilder

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

using SolimusWrapper.Builders;

var verbose = true;
var configuration = "Release";

var result = await new CommandBuilder("dotnet")
    .AddArgument("build")
    .AddFlag("--no-restore")
    .AddFlag("-v", verbose)
    .AddArgumentIfNotEmpty("-c", configuration)
    .AddArgumentIf(Environment.OSVersion.Platform == PlatformID.Unix, "--runtime", "linux-x64")
    .SetWorkingDirectory("/path/to/project")
    .SetTimeout(TimeSpan.FromMinutes(10))
    .SetStandardOutput(Console.WriteLine)
    .ExecuteAsync();

Методы CommandBuilder

Метод Описание
SetTarget(string) Устанавливает исполняемый файл
AddArgument(string) Добавляет один аргумент
AddArgument(string, string) Добавляет аргумент с значением
AddArguments(params string[]) Добавляет несколько аргументов
AddArgumentIf(bool, string) Условное добавление аргумента
AddArgumentIfNotEmpty(string, string?) Добавляет если значение не пустое
AddFlag(string, bool) Добавляет флаг если enabled = true
ClearArguments() Очищает все аргументы
SetWorkingDirectory(string) Устанавливает рабочую директорию
SetEnvironmentVariable(string, string?) Добавляет переменную окружения
SetStandardOutput(StringBuilder) Перенаправляет stdout в StringBuilder
SetStandardOutput(Action<string>) Перенаправляет stdout в делегат
SetStandardError(StringBuilder) Перенаправляет stderr в StringBuilder
MergeStandardOutputAndError(PipeTarget) Объединяет stdout и stderr
SetStandardInput(string) Устанавливает stdin
SetEncoding(Encoding) Устанавливает кодировку
SetValidation(bool) Включает/выключает проверку exit code
SetTimeout(TimeSpan) Устанавливает таймаут
OnExit(Action<int>) Callback при завершении
Build() Создаёт объект Command
ExecuteAsync() Строит и выполняет команду

🌐 Кросс-платформенные хелперы

using SolimusWrapper;

// Shell команда (cmd на Windows, sh на Unix)
var result = await CommandExtensions.Shell("echo Hello").ExecuteAndReadOutputAsync();

// Список файлов
var files = await CommandExtensions.ListFiles().ExecuteAndReadOutputAsync();
var files2 = await CommandExtensions.ListFiles("/path/to/dir").ExecuteAndReadOutputAsync();

// Текущая директория
var pwd = await CommandExtensions.GetCurrentDirectory().ExecuteAndReadOutputAsync();

// Echo
await CommandExtensions.Echo("Hello, World!").ExecuteAsync();

// Sleep
await CommandExtensions.Sleep(5).ExecuteAsync();

// Ping
await CommandExtensions.Ping("google.com", count: 4)
    .WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine))
    .ExecuteAsync();

// Переменная окружения
var path = await CommandExtensions.GetEnvironmentVariable("PATH").ExecuteAndReadOutputAsync();

// Поиск файлов
var found = await CommandExtensions.FindFiles("*.cs", "/path/to/search").ExecuteAndReadOutputAsync();

// Проверка существования файла
var exists = await CommandExtensions.FileExists("myfile.txt").ExecuteAndReadOutputAsync();

📊 API Reference

Command

Метод Описание
Run(string) Создаёт новую команду
WithArguments() Устанавливает аргументы
WithWorkingDirectory() Устанавливает рабочую директорию
WithEnvironmentVariable() Добавляет переменную окружения
WithEnvironmentVariables() Добавляет несколько переменных
WithStandardOutputPipe() Перенаправляет stdout
WithStandardErrorPipe() Перенаправляет stderr
WithStandardInputPipe() Устанавливает stdin
WithEncoding() Устанавливает кодировку
WithValidation() Включает/выключает проверку exit code
WithTimeout() Устанавливает таймаут
OnExit() Callback при завершении
ExecuteAsync() Выполняет команду
ExecuteAndReadOutputAsync() Выполняет и возвращает stdout
ExecuteAndReadAllAsync() Выполняет и возвращает stdout + stderr

PipeTarget

Метод Описание
Null Отбрасывает вывод
ToStringBuilder(sb) В StringBuilder
ToDelegate(action) Вызывает action для каждой строки
ToStream(stream) В поток
ToFile(path) В файл

PipeSource

Метод Описание
Null Пустой ввод
FromString(text) Из строки
FromStream(stream) Из потока
FromFile(path) Из файла
FromBytes(data) Из массива байтов

CommandResult

Свойство/Метод Описание
ExitCode Код выхода процесса
IsSuccess true если ExitCode == 0
StartTime Время запуска
ExitTime Время завершения
RunTime Длительность выполнения
EnsureSuccess() Выбрасывает исключение если ExitCode != 0

🧪 Примеры

Git операции

// Статус репозитория
var status = await Command.Run("git")
    .WithArguments("status", "--short")
    .WithWorkingDirectory("/path/to/repo")
    .ExecuteAndReadOutputAsync();

// Коммит
await Command.Run("git")
    .WithArguments("commit", "-m", "feat: add new feature")
    .ExecuteAsync();

// Pull с таймаутом
await Command.Run("git")
    .WithArguments("pull", "--rebase")
    .WithTimeout(TimeSpan.FromMinutes(2))
    .ExecuteAsync();

Docker

// Запуск контейнера
await Command.Run("docker")
    .WithArguments("run", "--rm", "-d", "-p", "8080:80", "nginx")
    .ExecuteAsync();

// Логи контейнера
await Command.Run("docker")
    .WithArguments("logs", "-f", "my-container")
    .WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine))
    .WithTimeout(TimeSpan.FromSeconds(30))
    .ExecuteAsync();

// Docker Compose
await Command.Run("docker-compose")
    .WithArguments("up", "-d")
    .WithWorkingDirectory("/path/to/project")
    .WithEnvironmentVariable("COMPOSE_PROJECT_NAME", "myapp")
    .ExecuteAsync();

.NET CLI

// Сборка проекта
var buildOutput = new StringBuilder();

var result = await Command.Run("dotnet")
    .WithArguments("build", "-c", "Release", "--no-restore")
    .WithStandardOutputPipe(PipeTarget.ToStringBuilder(buildOutput))
    .WithWorkingDirectory("/path/to/solution")
    .ExecuteAsync();

if (result.IsSuccess)
{
    Console.WriteLine("Build succeeded!");
    Console.WriteLine(buildOutput);
}

// Запуск тестов
await Command.Run("dotnet")
    .WithArguments("test", "--logger", "console;verbosity=detailed")
    .WithStandardOutputPipe(PipeTarget.ToDelegate(line =>
    {
        if (line.Contains("Passed") || line.Contains("Failed"))
            Console.WriteLine(line);
    }))
    .ExecuteAsync();

// Публикация
await new CommandBuilder("dotnet")
    .AddArgument("publish")
    .AddArgument("-c", "Release")
    .AddArgument("-o", "./publish")
    .AddFlag("--self-contained")
    .AddArgumentIf(OperatingSystem.IsLinux(), "-r", "linux-x64")
    .AddArgumentIf(OperatingSystem.IsWindows(), "-r", "win-x64")
    .ExecuteAsync();

FFmpeg

// Конвертация видео
await Command.Run("ffmpeg")
    .WithArguments(
        "-i", "input.mp4",
        "-c:v", "libx264",
        "-crf", "23",
        "-c:a", "aac",
        "-b:a", "128k",
        "output.mp4")
    .WithStandardErrorPipe(PipeTarget.ToDelegate(Console.WriteLine))
    .WithTimeout(TimeSpan.FromHours(1))
    .ExecuteAsync();

// Извлечение аудио
await Command.Run("ffmpeg")
    .WithArguments("-i", "video.mp4", "-vn", "-acodec", "mp3", "audio.mp3")
    .ExecuteAsync();

npm / Node.js

// Установка зависимостей
await Command.Run("npm")
    .WithArguments("install")
    .WithWorkingDirectory("/path/to/frontend")
    .WithEnvironmentVariable("NODE_ENV", "development")
    .ExecuteAsync();

// Запуск скрипта
await Command.Run("npm")
    .WithArguments("run", "build")
    .WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine))
    .ExecuteAsync();

⚡ Оптимизации

Библиотека оптимизирована для производительности:

Аспект Реализация
Memory ArrayPool<char> для буферов чтения
ValueTask Меньше аллокаций для sync-path
Record struct CommandResult размещается на стеке
file sealed Внутренние классы скрыты от API
Trimming Полная поддержка Native AOT

🛠️ Сборка из исходников

# Клонировать репозиторий
git clone https://github.com/yourname/SolimusWrapper.git
cd SolimusWrapper

# Восстановить зависимости
dotnet restore

# Собрать
dotnet build

# Запустить тесты
dotnet test

# Запустить демо
dotnet run --project samples/SolimusWrapper.Demo

# Создать NuGet пакет
dotnet pack -c Release

📄 Лицензия

MIT License. См. LICENSE для подробностей.

🤝 Contributing

Contributions welcome! Пожалуйста, создайте issue или pull request.

  1. Fork репозитория
  2. Создайте feature branch (git checkout -b feature/amazing-feature)
  3. Commit изменения (git commit -m 'Add amazing feature')
  4. Push в branch (git push origin feature/amazing-feature)
  5. Откройте Pull Request

📞 Связь

  • GitHub Issues: Issues
  • Email: salawat1302@gmail.com
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 173 1/1/2026
1.0.1 151 1/1/2026
1.0.0 144 12/30/2025