You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET Core控制台应用中实现Shell命令的交互式循环执行?

解决交互式命令执行与循环交互问题

你的现有代码只能处理一次性执行的命令,无法应对ssh这类需要用户输入回应的交互式场景。要实现实时输出命令结果并支持用户输入,需要修改成异步读取输出流、监听用户输入并写入进程标准输入的模式,具体实现如下:

核心修改思路

  • 开启RedirectStandardInput,允许向进程输入内容
  • 异步读取StandardOutput和StandardError,实时输出到控制台
  • 单独监听用户输入,将输入内容转发给进程的标准输入
  • 保持循环直到进程退出

完整代码示例

using System;
using System.Diagnostics;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        await RunInteractiveCommand("ssh", "100.100.109.86");
    }

    static async Task RunInteractiveCommand(string command, string args)
    {
        var process = new Process()
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = command,
                Arguments = args,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                RedirectStandardInput = true, // 开启标准输入重定向
                UseShellExecute = false,
                CreateNoWindow = true,
                // 确保编码匹配,避免乱码
                StandardOutputEncoding = System.Text.Encoding.UTF8,
                StandardErrorEncoding = System.Text.Encoding.UTF8
            }
        };

        // 异步读取输出流
        var outputTask = Task.Run(async () =>
        {
            string line;
            while ((line = await process.StandardOutput.ReadLineAsync()) != null)
            {
                Console.WriteLine(line);
            }
        });

        // 异步读取错误流
        var errorTask = Task.Run(async () =>
        {
            string line;
            while ((line = await process.StandardError.ReadLineAsync()) != null)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(line);
                Console.ResetColor();
            }
        });

        // 监听用户输入并写入进程标准输入
        var inputTask = Task.Run(async () =>
        {
            string input;
            while (!process.HasExited)
            {
                if (Console.KeyAvailable)
                {
                    input = Console.ReadLine();
                    await process.StandardInput.WriteLineAsync(input);
                    await process.StandardInput.FlushAsync();
                }
                await Task.Delay(100); // 避免过度占用CPU
            }
        });

        process.Start();

        // 等待所有任务完成
        await Task.WhenAll(outputTask, errorTask, inputTask);
        process.WaitForExit();
    }
}

关键细节说明

  • 异步流读取:用ReadLineAsync()逐行读取输出,避免ReadToEnd()阻塞到进程结束,实现实时输出
  • 标准输入转发:开启RedirectStandardInput后,将用户在控制台的输入写入进程的标准输入,满足交互式命令的输入需求
  • 编码设置:指定UTF8编码防止输出乱码,适配多数命令行工具的编码
  • CPU占用优化:用户输入监听循环中加入Task.Delay(100),避免无意义的空循环消耗过多资源

如果需要支持用户执行多个命令(比如执行完一个命令后回到自定义的命令提示符),可以在外层套一个循环,比如:

static async Task Main(string[] args)
{
    while (true)
    {
        Console.Write("> ");
        var userInput = Console.ReadLine();
        if (string.IsNullOrWhiteSpace(userInput)) continue;
        if (userInput.Equals("exit", StringComparison.OrdinalIgnoreCase)) break;

        // 拆分命令和参数(简单拆分,复杂场景需用命令行解析库)
        var parts = userInput.Split(' ', StringSplitOptions.RemoveEmptyEntries);
        if (parts.Length == 0) continue;
        var command = parts[0];
        var argsStr = string.Join(" ", parts[1..]);

        await RunInteractiveCommand(command, argsStr);
    }
}

这样用户就可以在自定义提示符下输入多个命令,包括交互式命令。

内容的提问来源于stack exchange,提问作者Vinyl Warmth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:01:38