C#中如何让cmd.exe输出同时显示在窗口并保存到变量
问题
我开发了一个用于下载和转换音频文件的简易XAML应用,点击下载按钮时会执行yt-dlp,通过ProcessStartInfo的RedirectStandardOutput属性捕获其输出并解析文件名供后续使用,但这样cmd.exe窗口不会打印任何内容。请问是否有办法既能让输出在cmd.exe窗口中打印,又能将输出保存到变量中?
以下是我的执行命令函数代码:
private void StartProcess(string args) { Process process = new Process(); { process.StartInfo = new ProcessStartInfo() { FileName = "cmd.exe", Arguments = args, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; } process.Start(); string out = process.ReadToEnd(); process.WaitForExit(); return; }
解决方案
要同时实现cmd窗口输出内容和捕获输出到变量,可以采用以下两种可行方案:
方案一:异步监听输出流,同时同步显示内容
取消阻塞式的ReadToEnd,改用异步监听进程的输出/错误流,一边将内容存入变量,一边将内容打印到控制台(或XAML应用的UI控件中模拟cmd输出效果)。同时设置CreateNoWindow=false确保cmd窗口正常显示:
private async Task<string> StartProcessAndCaptureOutput(string args) { var outputBuilder = new StringBuilder(); using (var process = new Process()) { process.StartInfo = new ProcessStartInfo() { FileName = "cmd.exe", Arguments = args, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = false, // 显示cmd窗口 StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; // 监听标准输出 process.OutputDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { outputBuilder.AppendLine(e.Data); Console.WriteLine(e.Data); // 同步打印到控制台,也可替换为UI控件更新 } }; // 监听错误输出 process.ErrorDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { outputBuilder.AppendLine(e.Data); Console.WriteLine(e.Data); } }; process.Start(); // 启动异步读取流 process.BeginOutputReadLine(); process.BeginErrorReadLine(); await process.WaitForExitAsync(); } return outputBuilder.ToString(); // 返回捕获到的完整输出 }
注意:XAML应用中更新UI需要切换到主线程,可使用Dispatcher.Invoke来更新文本框等控件内容。
方案二:让yt-dlp同时输出到窗口和日志文件
修改yt-dlp的执行参数,让它将输出同时打印到cmd窗口和指定日志文件,之后读取日志文件内容到变量:
- 修改args参数,添加日志输出选项:
/c yt-dlp [你的下载参数] --log-file yt-dlp.log
- 进程结束后读取日志文件:
private void StartProcess(string args) { Process process = new Process(); process.StartInfo = new ProcessStartInfo() { FileName = "cmd.exe", Arguments = args, UseShellExecute = true, // 允许显示cmd窗口 CreateNoWindow = false }; process.Start(); process.WaitForExit(); // 读取日志文件内容到变量 string output = File.ReadAllText("yt-dlp.log", Encoding.UTF8); // 后续可根据需要处理output,比如解析文件名 }
这种方式无需处理流监听,但要注意日志文件的覆盖、存储路径和清理问题。
内容的提问来源于stack exchange,提问作者BattleritePump
相关产品推荐
相关产品推荐

