C#中使用CliWrap控制CLI应用写入输入时报错的问题
问题分析与修正方案
你的代码存在三个关键错误,导致无法向CLI应用动态写入输入:
直接实例化抽象类
Stream:Stream是抽象基类,不能通过new Stream()直接创建实例,必须使用具体实现(如MemoryStream),但这只是编译层面的问题,不是运行时报错的核心原因。错误选择输入源类型:
PipeSource.FromStream是为静态预定义输入设计的——它会立即读取整个流的全部内容,随后关闭流。当你在监听进程输出时尝试用StreamWriter写入该流,流已经被CliWrap关闭,必然触发写入失败的报错。流的生命周期与交互逻辑不匹配:你试图在动态响应进程输出的同时写入同一个流,但
FromStream的一次性消费逻辑完全不支持这种交互式输入场景。
修正后的代码
使用CliWrap提供的PipeSource.Create创建支持动态写入的交互式输入源,这样可以在监听进程输出时实时写入输入:
using CliWrap; using CliWrap.EventStream; using System.IO.Pipelines; using System.Text; PipeWriter? inputWriter = null; // 创建支持动态写入的输入管道 await using var inputPipe = PipeSource.Create(async (writer, cancellationToken) => { inputWriter = writer; // 保持管道开放,直到外部调用CompleteAsync await Task.Delay(Timeout.Infinite, cancellationToken); }); var cmd = Cli.Wrap("longRunningProcess") .WithStandardInputPipe(inputPipe); await foreach (var cmdEvent in cmd.ListenAsync()) { switch (cmdEvent) { case StartedCommandEvent started: Debug.WriteLine($"Process started; ID: {started.ProcessId}"); break; case StandardOutputCommandEvent stdOut: Debug.WriteLine($"Out> {stdOut.Text}"); if (stdOut.Text.Contains("expectedOutput")) { if (inputWriter is null) break; // 写入输入内容,包含换行符 var inputData = "1" + Environment.NewLine; var inputBytes = Encoding.UTF8.GetBytes(inputData); await inputWriter.WriteAsync(inputBytes); await inputWriter.FlushAsync(); } break; case StandardErrorCommandEvent stdErr: Debug.WriteLine($"Err> {stdErr.Text}"); break; case ExitedCommandEvent exited: Debug.WriteLine($"Process exited; Code: {exited.ExitCode}"); // 完成输入管道,释放资源 if (inputWriter is not null) await inputWriter.CompleteAsync(); break; } }
关键说明
PipeSource.Create允许你获取一个PipeWriter实例,通过它可以在任意时机向进程的标准输入写入数据,完美适配交互式场景。- 保持输入管道开放直到进程退出,避免提前关闭导致写入失败。
- 写入时确保使用目标CLI应用期望的编码(通常为UTF-8),换行符可根据CLI平台选择
Environment.NewLine(自动适配Windows/Linux)或直接指定\r\n/\n。
内容的提问来源于stack exchange,提问作者ALMAAA
相关产品推荐
相关产品推荐

