ShellLibrary.Cmd 0.1.2

dotnet add package ShellLibrary.Cmd --version 0.1.2
                    
NuGet\Install-Package ShellLibrary.Cmd -Version 0.1.2
                    
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="ShellLibrary.Cmd" Version="0.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ShellLibrary.Cmd" Version="0.1.2" />
                    
Directory.Packages.props
<PackageReference Include="ShellLibrary.Cmd" />
                    
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 ShellLibrary.Cmd --version 0.1.2
                    
#r "nuget: ShellLibrary.Cmd, 0.1.2"
                    
#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 ShellLibrary.Cmd@0.1.2
                    
#: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=ShellLibrary.Cmd&version=0.1.2
                    
Install as a Cake Addin
#tool nuget:?package=ShellLibrary.Cmd&version=0.1.2
                    
Install as a Cake Tool

ShellLibrary.Cmd 完全指南

ShellLibrary.Cmd 是一个为 .NET 应用程序设计的声明式交互式 Shell 框架。你只需要进行简单的配置和命令注册,就能为你的应用快速嵌入一个功能完整、风格可定制的命令行界面(CLI)。它支持管道、外部二进制调用、打字机效果、安全锁定以及批处理脚本执行等特性。

1. 快速开始

首先,在你的项目中引用 ShellLibrary.Cmd 命名空间:

using ShellLibrary.Cmd;

然后,通过静态的 MainLibrary.BuildShell 来配置 Shell 的基本属性并启动它:

// 获取全局 Shell 设置实例
var setting = MainLibrary.BuildShell.ShellSetting;

// 配置 Shell 的外观信息
setting.ShellName = "TutorialShell";
setting.ShellVerion = "0.1";
setting.ShellDescription = "ShellLibrary.Cmd 教程示例";
setting.ShellWelcomeTemplate = true;      // 显示欢迎屏幕
setting.ShellTypwriterstyle = true;       // 启用打字机效果

// (可选)获取命令注册器并添加命令(详见第 2 节)
var registrar = new Register.CommandInfoMake();
registrar.MakeCommandInfo(...);

// 启动 Shell 交互循环
var shell = new MainLibrary.BuildShell();
await shell.BuildAsync();

运行后,你会看到一个带有欢迎屏幕和提示符 > 的命令行交互界面。


2. 命令注册与执行

所有 Shell 内部的命令都需通过 Register.CommandInfoMake 进行注册。每个命令包含名称、描述、用法、帮助文本以及一个执行委托 Func<string?, string[], Task<string>>

2.1 注册一个简单命令

下面的例子注册了一个 echo 命令,它将用户输入的参数拼接后输出到控制台,并将该字符串作为返回值(用于管道传递)。

var registrar = new Register.CommandInfoMake();

registrar.MakeCommandInfo(
    name: "echo",
    description: "输出给定的文本到控制台。",
    usage: "echo <text>",
    commandHelp: "将后续所有参数拼接为字符串并输出。",
    commandAction: async (stdin, args) =>
    {
        var output = string.Join(" ", args);
        Console.WriteLine(output);
        return output;
    }
);

2.2 命令委托参数说明

  • stdin:来自管道中上一个命令传递过来的标准输入字符串。如果该命令不是管道中的一环,则该参数为 null
  • args:用户输入中除去命令名以外的参数数组。
  • 返回值:一个字符串,它会作为当前命令的输出,传递给管道中的下一个命令。如果命令位于管道末尾,则返回值被忽略。

注意:ShellLibrary.Cmd 不会自动将命令返回值打印到控制台。如果你想在控制台上看到输出,必须在命令委托中主动调用 Console.WriteConsole.WriteLine

2.3 批量注册命令

如果你有大量命令,可以使用 BatchMakeCommandInfoAllListCommandInfo 进行批量注册。

var commandList = new List<Register.CommandRegisterInfo>
{
    new Register.CommandRegisterInfo { Name = "cmd1", ... },
    new Register.CommandRegisterInfo { Name = "cmd2", ... }
};
registrar.BatchMakeCommandInfo(commandList);

3. 管道支持

ShellLibrary.Cmd 原生支持使用管道符(默认 |)连接多个命令。在解析时,前一个命令的返回值会被自动传递给后一个命令的 stdin 参数。

示例:假设我们注册了 reverse 命令,它反转输入的字符串。

registrar.MakeCommandInfo(
    name: "reverse",
    description: "反转输入的文本。",
    usage: "reverse",
    commandHelp: "将标准输入或参数中的文本反转。",
    commandAction: async (stdin, args) =>
    {
        var input = stdin ?? string.Join(" ", args);
        var reversed = new string(input.Reverse().ToArray());
        Console.WriteLine(reversed);
        return reversed;
    }
);

用户即可使用管道组合命令:

> echo hello world | reverse
dlrow olleh

你可以通过 MainLibrary.BuildShell.ShellSetting.ShellDelimiter 更改管道分隔符。


4. 调用外部二进制文件

默认情况下,如果用户输入的命令名是一个存在于磁盘上的文件路径(例如 ping/bin/ls),ShellLibrary.Cmd 会尝试启动该文件作为外部进程执行。

此行为由 ShellSetting.ShellRunBinary 控制:

  • true(默认):允许执行外部可执行文件。
  • false:禁止执行任何外部二进制,仅执行内部注册的命令。这有助于创建安全的“受限” Shell 环境。
MainLibrary.BuildShell.ShellSetting.ShellRunBinary = false;

当用户试图执行外部程序时,Shell 将返回 “Command not found.”。


5. 打字机效果与视觉定制

通过配置 TypeWriterShellSetting,你可以控制 Shell 的视觉效果。

5.1 启用打字机效果

setting.ShellTypwriterstyle = true;

启用后,欢迎屏幕的文字会逐字打印,营造复古终端体验。你也可以在自定义命令中调用 MainLibrary.BuildShell.TypeWriter.Write 实现类似效果。

5.2 其他视觉配置

属性 说明
ShellCursorVisible 是否显示控制台光标(true / false
ShellTitle 是否将 Shell 名称设置为控制台窗口标题
ShellWelcomeTemplate 是否在启动时显示欢迎屏幕
setting.ShellCursorVisible = true;
setting.ShellTitle = true;

6. 安全特性:锁定与受限模式

ShellLibrary.Cmd 提供两种维度的安全锁定机制。

6.1 禁止执行外部二进制

如第 4 节所述,设置 ShellRunBinary = false 可以完全阻止用户启动任何外部程序。

6.2 自定义“认知牢笼”

由于命令必须显式注册,你可以通过只注册少量安全命令,来构建一个功能极简的受限 Shell。结合 ShellRunBinary = false,用户即使知道系统命令的路径也无法执行。

setting.ShellRunBinary = false;
registrar.MakeCommandInfo("ls", ...); // 只允许 ls

这种方案比传统 rbash 更加彻底,因为用户无法通过任何方式接触到未注册的命令。


7. 历史记录

ShellLibrary.Cmd 自动记录用户输入的历史命令。记录保存在当前目录的 history.txt 文件中,每条记录附带时间戳。

你可以通过 MainLoop 实例控制该行为:

MainLibrary.BuildShell.MainLoop.HistoryCommandWriteEnabled = false;  // 关闭历史记录

8. 安全退出与信号处理

Shell 内部处理了 Ctrl+C 信号。按一次不会退出;连续按两次将触发安全退出逻辑:先尝试终止正在运行的外部进程(如果有),然后退出 Shell。

你可以通过 MainLoop 的属性进行调整:

var loop = MainLibrary.BuildShell.MainLoop;
loop.SafeExitEnabled = true;      // 是否启用安全退出(按两次 Ctrl+C)
loop.EnabledShellExit = true;     // 是否允许退出 Shell

9. 剧本解析器(批处理脚本)

ShellLibrary.Cmd 包含一个实验性的批处理脚本解析器 SpecializedControlScriptParser,它可以将文本文件中每一行作为命令送入 Shell 执行。

var parser = new SpecializedControlScriptParser();
await parser.Parser("commands.txt");

这对于自动化任务或 CI 场景非常实用。注意:该功能在 0.1.0 版本中已稳定可用,适合小型脚本文件。


10. 高级自定义:消息与提示符

10.1 自定义提示符

MainLibrary.BuildShell.MainLoop.GetTipText = "$ ";   // 默认为 ">"

10.2 自定义错误消息

MessageReops 类包含一个字典,你可以覆盖默认的错误提示。

MainLibrary.BuildShell.MessageReops.Messages["CommandNotFound"] = "未知命令,请输入 help 查看可用命令。";

11. 完整示例:构建一个带帮助系统的迷你 Shell

using ShellLibrary.Cmd;
using ShellLibrary.Cmd.Command;

// 配置 Shell
var setting = MainLibrary.BuildShell.ShellSetting;
setting.ShellName = "MiniShell";
setting.ShellVerion = "1.0";
setting.ShellDescription = "一个带帮助系统的示例 Shell";
setting.ShellWelcomeTemplate = true;
setting.ShellTypwriterstyle = true;
setting.ShellRunBinary = false;

var registrar = new Register.CommandInfoMake();

// 注册 echo 命令
registrar.MakeCommandInfo("echo", "输出文本。", "echo <text>", "打印所有参数。",
    async (stdin, args) => { var s = string.Join(" ", args); Console.WriteLine(s); return s; });

// 注册 clear 命令
registrar.MakeCommandInfo("clear", "清屏。", "clear", "清除控制台内容。",
    async (stdin, args) => { Console.Clear(); return ""; });

// 注册 help 命令
registrar.MakeCommandInfo("help", "显示帮助。", "help", "列出所有命令。",
    async (stdin, args) =>
    {
        foreach (var cmd in MainLibrary.BuildShell.CommandRepository.Commands)
            Console.WriteLine($"{cmd.Key,-10} - {cmd.Value.Description}");
        return "";
    });

// 启动
var shell = new MainLibrary.BuildShell();
await shell.BuildAsync();

12. 结语

ShellLibrary.Cmd 的设计目标是让 .NET 开发者能够以最小的代价,为应用程序赋予一个专业、安全且高度可定制的命令行交互界面。无论是用于调试、管理工具、游戏控制台还是嵌入式设备,它都能提供一套一致且强大的解决方案。

关于 API 的更多细节,请查阅源码注释或项目的 GitHub 仓库。

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • 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
0.1.2 124 4/11/2026
0.1.1 112 4/10/2026
0.1.0-pre 117 4/10/2026