C#下写GUI - 管道操作 - 读取标准输出流 - 截获shell程序输出
2009-03-22 18:49
351 查看
这是个老话题了,可是折磨了我N个各月,我太笨了。某天终于很灵异地成功了,苦心人,天不负……
现在还有太多的程序用命令行(为啥都喜欢用呢,看起来很professional?),可整天敲参数、看黑白屏幕总不太爽吧?
GUI作用就是把这种“黑白屏幕”变成图形界面,看起来多舒服,是不是?
最初这个问题是在x264编码器出现的。这是个命令行程序,想写个GUI。我真是自不量力呀,刚接触程序没几天就敢充胖子,一上来就碰壁,求google大神,有所收获。不过我模仿就是实现不了,太笨了。
终于好了,有两个方法:一个是用StreamReader主动读取;另一个是用异步读取,应用回调函数。
个人认为前一种适合内容比较大多的情况,后一种适合比较少的情况。
先说第一种吧,
先引用需要的命名空间
using System.Diagnostics;
using System.Threading;
然后添加一个方法,我直接用了Button,触发整个代码,下面是一些类级的声明
Process p;
delegate void chandle(string s);
private void button1_Click(object sender, EventArgs e)
{
Thread tt = new Thread(new ThreadStart(t));
tt.Start();
}
在这里,新建了一个线程,我可不喜欢在主线程上跑,影响美观,下面写t()这个方法。
1 private void t()
2 {
3 p = new Process();
4 p.StartInfo.FileName = "azid.exe";
5 p.StartInfo.Arguments = @"I:\kn\m12\m12..ac3 I:\kn\m12\au2.wav";
6
7 p.StartInfo.CreateNoWindow = true;
8 p.StartInfo.UseShellExecute = false;
9 p.StartInfo.RedirectStandardError = true;
p.Start();
Thread rt = new Thread(new ThreadStart(read));
rt.Start();
p.WaitForExit();
p.Dispose();
}
在这里,创建一个Process类的实例,然后对StartInfo属性进行设置,主要是为了不要让他显示命令行窗口,并且把输出流RedirectStandardError导出,
这里多说一句,我这个程序azid的输出都被塞到了StandardError(标准错误输出)里面,貌似x264也是,你要注意一下你的程序输出是在标准输出还是错误输出,依次尝试一下即可,之后再创建一个线程,用来运行我们的读取函数,具体关系看下面这张涂鸦。
下面写读取函数read()
private void read()
{
StreamReader sr = p.StandardError;
while (!p.HasExited)
{
Invoke(new chandle(ct), sr.ReadLine());
Thread.Sleep(20);
}
}
这里用Invoke来控制主界面上的控件,因为这里是线程rt,不能直接操作主线程厄,我在这里弱智了N久,一直研究怎么做线程同步,其实是迷失了方向,偶然才发现Invoke方法的强大。
这里挂接的委托ct用来更新主界面的textbox,显示读取出来的内容,把sr.ReadLine()做参数传进去。
private void ct(string s)
{
textBox1.AppendText(s.Trim() + "\n");
textBox1.SelectionStart = textBox1.Text.Length - 1;
Application.DoEvents();
6 }
就是这样了哈……于是就可以工作了,不过这个程序有点问题,while (!p.HasExited)这里的条件有点单薄,容易异常掉,我比较懒
下面说说异步读取,这个好像比上面的简单。
1 Process p;
2 delegate void chandle(string s);
3
4
5 private void button1_Click(object sender, EventArgs e)
6 {
7 Thread tt = new Thread(new ThreadStart(t));
8 tt.Start();
9 }
private void t()
{
p = new Process();
p.StartInfo.FileName = "azid.exe";
p.StartInfo.Arguments = @"I:\kn\m12\m12..ac3 I:\kn\m12\au2.wav";
p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);//这里多了这句
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.Start();
p.BeginErrorReadLine(); //这里多了这句
p.WaitForExit();
p.Dispose();
}
和第一种方法差不多,只不过多了2句,第一句为ErrorDataReceived添加一个事件处理函数,就是那个回调函数,第二句开始读取
void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Data))
{
// 做点工作
}
}
程序每向输出流写入一行时,触发一次这个事件,e.Data属性可以获得这一行数据,然后怎么处理就看你了。
这个方法如果你的输出流行数很多,那就要不断地调用这个函数,很费资源orz,到底用哪个,根据情况判断吧,当然你也可以2个交错使用,在msdn上有写限制条件
地址在这里:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.standarderror(VS.80).aspx
现在还有太多的程序用命令行(为啥都喜欢用呢,看起来很professional?),可整天敲参数、看黑白屏幕总不太爽吧?
GUI作用就是把这种“黑白屏幕”变成图形界面,看起来多舒服,是不是?
最初这个问题是在x264编码器出现的。这是个命令行程序,想写个GUI。我真是自不量力呀,刚接触程序没几天就敢充胖子,一上来就碰壁,求google大神,有所收获。不过我模仿就是实现不了,太笨了。
终于好了,有两个方法:一个是用StreamReader主动读取;另一个是用异步读取,应用回调函数。
个人认为前一种适合内容比较大多的情况,后一种适合比较少的情况。
先说第一种吧,
先引用需要的命名空间
using System.Diagnostics;
using System.Threading;
然后添加一个方法,我直接用了Button,触发整个代码,下面是一些类级的声明
Process p;
delegate void chandle(string s);
private void button1_Click(object sender, EventArgs e)
{
Thread tt = new Thread(new ThreadStart(t));
tt.Start();
}
在这里,新建了一个线程,我可不喜欢在主线程上跑,影响美观,下面写t()这个方法。
1 private void t()
2 {
3 p = new Process();
4 p.StartInfo.FileName = "azid.exe";
5 p.StartInfo.Arguments = @"I:\kn\m12\m12..ac3 I:\kn\m12\au2.wav";
6
7 p.StartInfo.CreateNoWindow = true;
8 p.StartInfo.UseShellExecute = false;
9 p.StartInfo.RedirectStandardError = true;
p.Start();
Thread rt = new Thread(new ThreadStart(read));
rt.Start();
p.WaitForExit();
p.Dispose();
}
在这里,创建一个Process类的实例,然后对StartInfo属性进行设置,主要是为了不要让他显示命令行窗口,并且把输出流RedirectStandardError导出,
这里多说一句,我这个程序azid的输出都被塞到了StandardError(标准错误输出)里面,貌似x264也是,你要注意一下你的程序输出是在标准输出还是错误输出,依次尝试一下即可,之后再创建一个线程,用来运行我们的读取函数,具体关系看下面这张涂鸦。
下面写读取函数read()
private void read()
{
StreamReader sr = p.StandardError;
while (!p.HasExited)
{
Invoke(new chandle(ct), sr.ReadLine());
Thread.Sleep(20);
}
}
这里用Invoke来控制主界面上的控件,因为这里是线程rt,不能直接操作主线程厄,我在这里弱智了N久,一直研究怎么做线程同步,其实是迷失了方向,偶然才发现Invoke方法的强大。
这里挂接的委托ct用来更新主界面的textbox,显示读取出来的内容,把sr.ReadLine()做参数传进去。
private void ct(string s)
{
textBox1.AppendText(s.Trim() + "\n");
textBox1.SelectionStart = textBox1.Text.Length - 1;
Application.DoEvents();
6 }
就是这样了哈……于是就可以工作了,不过这个程序有点问题,while (!p.HasExited)这里的条件有点单薄,容易异常掉,我比较懒
下面说说异步读取,这个好像比上面的简单。
1 Process p;
2 delegate void chandle(string s);
3
4
5 private void button1_Click(object sender, EventArgs e)
6 {
7 Thread tt = new Thread(new ThreadStart(t));
8 tt.Start();
9 }
private void t()
{
p = new Process();
p.StartInfo.FileName = "azid.exe";
p.StartInfo.Arguments = @"I:\kn\m12\m12..ac3 I:\kn\m12\au2.wav";
p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);//这里多了这句
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.Start();
p.BeginErrorReadLine(); //这里多了这句
p.WaitForExit();
p.Dispose();
}
和第一种方法差不多,只不过多了2句,第一句为ErrorDataReceived添加一个事件处理函数,就是那个回调函数,第二句开始读取
void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Data))
{
// 做点工作
}
}
程序每向输出流写入一行时,触发一次这个事件,e.Data属性可以获得这一行数据,然后怎么处理就看你了。
这个方法如果你的输出流行数很多,那就要不断地调用这个函数,很费资源orz,到底用哪个,根据情况判断吧,当然你也可以2个交错使用,在msdn上有写限制条件
地址在这里:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.standarderror(VS.80).aspx
相关文章推荐
- p16.2编写一个程序,从标准输入读取几行输入,每行输入都要打印到标准输出上,前面要加上行号,书入行的长度没有限制
- 编写一个程序,从标准输入读取几行输入。每行输入都要打印到标准输出上,前面加上行号。在编写这个程序的时候要使这个程序能够处理的输入行的长度没有限制
- C语言 编写一个程序从标准输入读取字符,并把他们写到标准输出。除了大写字母转换成小写字母之外,其他的原样输出。
- 编写一个程序,从标准输入读取几行输入。每行输入都要打印到标准输出上,前面要加上行号。
- 利用管道获取控制台程序的标准输出
- Shell行操作:逐行读取,指定行输出,指定行删除等
- 【c语言】编写一个程序,从标准输入读取几行输入。每行输入都要打印到标准输出上,前面加上行号。在编写这个程序的时候要使这个程序能够处理的输入行的长度没有限制。
- 2. 编写一个程序,从标准输入读取几行输入。每行输入都要打印到标准输出上,前面加上行号。在编写这个程序的时候要使用让这个程序能够处理的输入行的长度没有限制
- Java中截获标准输出到GUI控件
- 利用管道获取控制台程序的标准输出
- 编写一个程序从标准输入读取字符,并把他们写到标准输出。除了大写字母转换成小写字母之外,其他的原样输出。
- 程控制中关于搜索、控制计算机的功能 和 VB中截获shell程序的输出
- 编写一个程序从标准输入读取字符,并把他们写到标准输出。除了大写字母转换成小写字母之外,其他的原样输出。
- 编写程序从标准输入读取几行输入。每行输入都打印在标准输出上,且前面加上行号
- 编写一段程序,从标准输入中读取多个字串并将他么连接起来,输出成大的字符串。 改写上述程序,用空格把输入的多个字符串分割开来。
- c# .Net :Excel NPOI导入导出操作教程之读取Excel文件信息及输出
- Java中截获标准输出到GUI控件
- 【C语言】编写一个程序从标准输入读取字符,并把他们写到标准输出。除了大写字母转换成小写字母之外,其他的原样输出。
- 编写一个程序从标准输入读取字符,并把他们写到标准输出,除了大写字母转换成小写字母之外,其他的原样输出。
- shell从标准输出读取键盘输入