[C#,WinForm]进程输入、输出、错误流的重定向
来源:互联网 发布:centos rvm 安装ruby 编辑:程序博客网 时间:2024/05/21 13:22
首先,进程涉及的流有三种,输入流StandardInput、输出流StandardOutput、错误流StandardError,三者不可混淆,特别是输出流和错误流更是要注意不可混为一谈!比如在makefile编译过程中执行make命令,如果没有将错误流重定向输出,那么程序是不会显示原本应该打印的错误信息的。
一、同步方式
这里有一个简单编写的小例子,是一个win窗口程序。为点击按钮,在后台启动控制台,按照程序设定输入命令,并将返回的输出打印在文本框中,下面是核心代码——按钮点击的响应函数。这里存在着有诸多问题:
- private void button1_Click(object sender, EventArgs e)
- {
- ProcessStartInfo start = new ProcessStartInfo("cmd.exe");
- start.CreateNoWindow = true; //不显示dos命令行窗口
- start.RedirectStandardOutput = true;
- start.RedirectStandardInput = true;
- start.RedirectStandardError = true;
- start.UseShellExecute = false; //是否指定操作系统外壳进程启动程序,这里需为false
- Process p = Process.Start(start);
- StreamWriter writer = p.StandardInput;
- writer.WriteLine("ping www.baidu.com");
- writer.WriteLine("exit");
- StreamReader reader = p.StandardOutput; //截取输出流
- StreamReader readerErr = p.StandardError; //截取错误流
- string line = reader.ReadLine();
- while (!reader.EndOfStream)
- {
- tbResult.AppendText(line+"\r\n");
- line = reader.ReadLine();
- }
- string lineErr = readerErr.ReadLine();
- while (!reader.EndOfStream)
- {
- tbResult.AppendText(lineErr + "\r\n");
- lineErr = readerErr.ReadLine();
- }
- p.WaitForExit(); //等待程序执行完退出进程
- p.Close(); //关闭进程
- reader.Close(); //关闭流
- readerErr.Close();
- }
(1)子后台控制台执行命令开始执行至退出,主窗口会不响应用户操作,也就是通常说的阻塞,这可以通过多线程来解决。另建一线程在后台执行,调用进程启动函数,使之不影响主线程。
(2)程序中这种做法的硬伤是极有可能造成错误流输出的异常,当然在本程序中由于不存在错误流,故异常体现不出来。如果执行的是makefile编译的make命令,既有输出流又有错误流,如果想要通过这种方法在界面上同时显示输出和错误信息,是极不靠谱的,容易发生死锁。这个死锁缺陷也是同步读取重定向流的硬伤,如果一定要同时重定向错误流和输出流,最好使用异步读取重定向方式。采用异步的同时,也应采用多线程,因此对控件的操作要依照多线程的规范。下面是msdn的引述:
同步读取操作在读取StandardOutput 流的调用方及写入该流中的子进程之间引入一个依赖项。这些依赖项可能导致产生死锁情况。调用方读取子进程的重定向流时依赖于该子进程。调用方将等待读取操作,直到子进程写入流或关闭流为止。子进程写入足够多的数据以填充重定向流的时间依赖于父进程。子进程将等待下一次写操作,直到父进程读取了全部流或关闭该流为止。当调用方和子进程相互等待对方完成操作时,就会产生死锁情况,使双方都无法继续执行操作。您可以通过计算调用方和子进程之间的依赖项从而避免出现死锁情况。
二、多线程下的异步读取
- private void button1_Click(object sender, EventArgs e)
- {
- Thread th = new Thread(exeFile);
- th.IsBackground = true;
- th.Start();
- }
- private void exeFile()
- {
- ProcessStartInfo start = new ProcessStartInfo("cmd.exe");
- start.CreateNoWindow = true; //不显示dos命令行窗口
- start.RedirectStandardOutput = true;
- start.RedirectStandardInput = true;
- start.RedirectStandardError = true;
- start.UseShellExecute = false; //是否指定操作系统外壳进程启动程序,这里需为false
- Process p = Process.Start(start);
- StreamWriter writer = p.StandardInput;
- writer.WriteLine("ping www.baidu.com");
- writer.WriteLine("exit");
- writer.Close();
- p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
- p.BeginOutputReadLine();
- p.WaitForExit(); //等待程序执行完退出进程
- p.Close(); //关闭进程
- }
- void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
- {
- if (!string.IsNullOrEmpty(e.Data))
- {
- showText(tbResult, e.Data);
- }
- }
- private delegate void showTextDelegate(TextBox tb, string line);
- private void showText(TextBox tb, string line)
- {
- if (tb.InvokeRequired)
- {
- showTextDelegate d = showText;
- object[] a = { tb, line };
- tb.Invoke(d, a);
- }
- else
- {
- tb.AppendText(line + "\r\n");
- }
- }
三、其他
注意telnet.exe并不支持流的重定向。
0 0
- [C#,WinForm]进程输入、输出、错误流的重定向
- 进程输入、输出、错误流的重定向 .
- Java输出输入错误流重定向
- [Linux C语言](学习笔记)标准输入流输出流以及错误流的重定向机制(1)
- [Linux C语言](学习笔记)标准输入流输出流以及错误流的重定向机制(2)
- 重定向标准输入,输出以及错误流
- 重定向标准输入,输出以及错误流
- linux下输入流输出流错误流的重定向
- 重定向在标准输出流、输入流、错误流的应用
- C/C++输入/输出重定向
- C/C++输入/输出重定向
- C/C++输入/输出重定向
- 输入/输出重定向
- linux 重定向 标准输入 标准输出 标准错误输出
- Linux下的输入/输出重定向
- Linux下的输入/输出重定向
- Linux下的输入/输出重定向
- Linux下的输入/输出重定向
- android与服务器端交互(一)
- Opencv学习笔记——透视变换
- C程序常见错误30例
- 项目需求确认之后如何防止客户新增需求的蔓延?
- gdb学习资料
- [C#,WinForm]进程输入、输出、错误流的重定向
- PHP AJAX JSONP使用的实例
- POJ 1659Frogs' Neighborhood Havel-Hakimi定理判断可图
- Android: In-app-billing 付费机制Google示例
- POJ1887——Testing the CATCHER
- Android开发之Handler使用4个例子
- 使用try和catch捕获异常
- Redis源码分析(三十四)--- redis.h服务端的实现分析(1)
- 写python的c扩展简介