分享
 
 
 

如何获取子进程的输出

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

经常看到论坛中有人问到当用Process组件启动新的进程后,如何获取它的输出的问题。采取将子进程的输出定向到一个临时文件中,当然也可以解决问题。但是这样每次父进程从临时文件中获取信息后,还要删除该临时文件,毕竟比较麻烦。其实,Process提供了几个属性可以获取输出。在.net框架sdk的帮助文档里面就有这方面的例子,但是对于如何同时获取错误输出和标准输出方面没有给出具体代码,本文将给出实例并对管道的特性作一些说明。

一、获取子进程标准输出和错误输出的的方法:

我们写一个小程序p2.cs,用它来产生标准输出和错误输出。

//p2.cs代码如下:

using System;

class class1

{

public static void Main()

{

int i = 0;

string s1 = String.Format("out:{0,4}--------------------------------------------------",i);

System.Console.Out.WriteLine(s1);

string s2 = String.Format("err:{0,4}**************************************************",i);

System.Console.Error.WriteLine(s2);

}

}

编译成p2.exe

获取子进程的标准输出和错误输出的源程序

//p1.cs

....

Process p = new Process("p2.exe");

p.StartInfo.UseShellExecute = false; //指定不使用系统的外壳程序,而是直接启动被调用程序本身

p.StartInfo.RedirectStandardOutput = true; //只有将此属性设为true,才能通过管道获取子进程输出

p.StartInfo.RedirectStandardError = true;

p.Start(); //启动子进程

string output = p.StandardOutput.ReadToEnd(); //读取标准输出

string error = p.StandardError.ReadToEnd(); //读取错误输出

p.WaitForExit(); //等待子进程执行完毕

...

上例中,父进程启动子进程后,就等待着从管道中取走标准输出,取走全部标准输出后取走错误输出。我们运行起来没有任何错误。但是一旦我门增加p2.exe中的标准输出和错误输出的字节数:

for(i=0;i<200;i++)

System.Console.Out.WriteLine(s1);

for(i=0;i<200;i++)

System.Console.Error.WriteLine(s2);

编译后,再运行,就会发现父进程和子进程出现了死锁,只有强行关闭才能终止进程。

二、管道:

Process 组件通过管道与子进程进行通讯。如果同时重定向标准输出和标准错误,然后试图读取它们,当管道被填满时候就会出现问题。上例中,父进程只有读完了所有的标准输出才能读错误输出,而子进程的标准输出每当把管道填满时候,父进程都会取走,子进程接着向管道输出后续的标准输出。这都运行的很好。可是当子进程执行到输出错误输出的时候,由于子进程还没有运行结束,它的标准输出流就不会处于结束状态(虽然在我们的例子中它的200次循环的标准输出已经执行完毕),这就导致父进程中的ReadToEnd()方法不会执行完毕,所以父进程中的p.StandardError.ReadToEnd()无法执行,从而管道中的错误输出无法被读取,子进程的后续错误输出无法写入管道,最终子进程和父进程彼此无限等待,出现了阻塞情况。

子进程通过检查管道中最后一个字节是否被取走,来决定是否输出后续内容。也就是说,如果管道缓冲区中最后一个字节之前的所有内容都被取走,子进程仍然会处于等待中;如果前面所有字节都没有取走,但最后一个字节内容被取走,子进程会继续向管道里输出后续内容,当然这样只能输出一字节到管道中最后位置。

我们如果把p1.cs中的string output = p.StandardOutput.ReadToEnd()改为:

for(int i=0;i<200*60;i++)

Console.Write((char) p.StandardOutput.Read());

就不会出现死锁情况。因为当获取标准输出的循环执行完后,会接着执行获取错误输出的语句,而不需等待标准输出流的结束。但是这种方法毫无实际意义,因为实际中,我们并不可能像本例中知道标准输出会有多少字节。

三、用多线程分别获取标准输出和错误输出

对于这种情况,.net框架文档中建议这样解决:创建两个线程,以便应用程序可以在单独的线程上读取每个流的输出。下面给出例子:

//p1.cs:

...

class class1

{

.....

public static void Main()

{

ProcessStartInfo pi = new ProcessStartInfo();

pi.FileName = @"c:\p2.exe";

pi.UseShellExecute = false;

pi.RedirectStandardOutput = true;

pi.RedirectStandardError = true;

System.Diagnostics.Process p = new Process();

p.StartInfo = pi;

p.Start();

tout t1 = new tout(p);

terr t2 = new terr(p);

Thread thread1 = new Thread(new ThreadStart(t1.Read));

Thread thread2 = new Thread(new ThreadStart(t2.Read));

thread1.Start();

thread2.Start();

p.WaitForExit();

Console.WriteLine("p2.exe结束");

}

}

class tout

{

Process p;

public tout(Process p)

{

this.p = p;

}

public void Read()

{

int a = -1;

while((a = p.StandardOutput.Read()) > 0)

{

Console.Write( ((char) a).ToString() );

}

Thread.CurrentThread.Abort();

return;

}

}

class terr

{

Process p;

public terr(Process p)

{

this.p = p;

}

public void Read()

{

int a = -1;

while((a = p.StandardError.Read()) > 0)

{

Console.Write(((char) a).ToString());

}

Thread.CurrentThread.Abort();

return;

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有