如何获取子进程的输出

如何获取子进程的输出,第1张

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

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

我们写一个小程序p cs 用它来产生标准输出和错误输出 //p cs代码如下 using Systemclass class { public static void Main() {  int i =   string s = String Format( out:{ } i)  System Console Out WriteLine(s )  string s = String Format( err:{ }************************************************** i)  System Console Error WriteLine(s ) }}    编译成p exe

获取子进程的标准输出和错误输出的源程序//p cs Process p = new Process( p 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()//等待子进程执行完毕   上例中 父进程启动子进程后 就等待着从管道中取走标准输出 取走全部标准输出后取走错误输出 我们运行起来没有任何错误 但是一旦我门增加p exe中的标准输出和错误输出的字节数 for(i= i<i++) System Console Out WriteLine(s )for(i= i<i++) System Console Error WriteLine(s )编译后 再运行 就会发现父进程和子进程出现了死锁 只有强行关闭才能终止进程

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

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

我们如果把p cs中的string output = p StandardOutput ReadToEnd()改为  for(int i= i<* i++)  Console Write((char) p StandardOutput Read())

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

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

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

lishixinzhi/Article/program/net/201311/11610

将你要获取的类输出的内容存放在一个变量中,比如你输出的是一个字符串,那么久创建一个String对象来存放输出结果,就不要使用sysout输出了,然后在你要调用这个结果的类中,使用以下几种方法

继承方法,直接继承那个类,然后通过向下转型的方法,声明类,然后就可以用声明的对象去调用那个值了

直接用new来调用这个类,从而调用这个方法

如果不在一个包或者一个项目中,则需要进行导入


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7981263.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-12
下一篇 2023-04-12

发表评论

登录后才能评论

评论列表(0条)

保存