在Windows环境下的所谓shell程序就是dos命令行程序,比如VC的CL.exe命令行编译器,JDK的javac编译器,启动java程序用的java.exe都是标准的shell程序。截获一个shell程序的输出是很有用的,比如说您可以自己编写一个IDE(集成开发环境),当用户发出编译指令时候,你可以在后台启动shell 调用编译器并截获它们的输出,对这些输出信息进行分析后在更为友好的用户界面上显示出来。
为了方便起见,我们用C#作为本文的演示语言。
通常,系统启动Shell程序时缺省给定了3个I/O信道,标准输入(stdin), 标准输出stdout, 标准错误输出stderr。之所以这么区分是因为在早期的计算机系统如PDP-11的一些限制。那时没有GUI, 将输出分为stdout,stderr可以避免程序的调试信息和正常输出的信息混杂在一起。shell程序把它们的输出写入标准输出管道(stdout)、把出错信息写入标准错误管道(stderr)。缺省情况下,系统将管道的输出直接送到屏幕,这样一来我们就能看到应用程序运行结果了。
为了捕获一个标准控制台应用程序的输出,我们必须把standOutput和standError管道输出重定向到我们自定义的管道。
下面的代码可以启动一个shell程序,并将其输出截获。 // 实例一:WindowsForm应用程序
// 代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms;
namespace CommandTest { public partial class FrmRunCommand : Form { System.IO.StreamWriter sw; // 定义输出流 sw 作为Shell的标准输入,即命令 System.IO.StreamReader sr; // 定义输出流 sr 作为Shell的标准输出,即正常结果 System.IO.StreamReader err; // 定义输出流 err 作为Shell的错误输出,即出错结果 System.Diagnostics.Process p = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo psI = new System.Diagnostics.ProcessStartInfo(System.Environment.GetEnvironmentVariable("ComSpec"));
public FrmRunCommand() { InitializeComponent(); }
private void btnRun_Click(object sender, EventArgs e) { psI.UseShellExecute =false ; psI.RedirectStandardInput = true; psI.RedirectStandardOutput = true; psI.RedirectStandardError = true; psI.CreateNoWindow = true; p.StartInfo = psI;
Cursor = System.Windows.Forms.Cursors.WaitCursor;
p.Start(); sw = p.StandardInput; sr = p.StandardOutput; err = p.StandardError;
sw.AutoFlush = true;
if(coboCommand.Text != "") { sw.WriteLine(coboCommand.Text); } else { sw.WriteLine("echo 未输入命令"); } sw.Close();
tbResult.Text = "输出结果为:"+sr.ReadToEnd(); tbResult.Text += "\n错误信息:\n"+err.ReadToEnd();
Cursor = System.Windows.Forms.Cursors.Default; } } } // 程序运行结果:
// 实例二:Asp.net程序 // 实例二文件一:Default.aspx <%@ Page Language="C#" AutoEventWireup="true" validateRequest="false" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Shell程序运行测试页</title> </head> <body> <form runat="server"> <div> 请输入命令:<asp:TextBox runat="server" Width="375px"></asp:TextBox> <asp:Button runat="server" Text="执行命令" /><br /> <asp:TextBox runat="server" Height="343px" TextMode="MultiLine" Width="551px"></asp:TextBox> </div> </form> </body> </html>
// 实例二文件二:Default.aspx.cs using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page { System.IO.StreamWriter sw; // 定义输出流 sw 作为Shell的标准输入,即命令 System.IO.StreamReader sr; // 定义输出流 sr 作为Shell的标准输出,即正常结果 System.IO.StreamReader err; // 定义输出流 err 作为Shell的错误输出,即出错结果 System.Diagnostics.Process p = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo psI = new System.Diagnostics.ProcessStartInfo(System.Environment.GetEnvironmentVariable("ComSpec"));
protected void Page_Load(object sender, EventArgs e) { } protected void btnCommand_Click(object sender, EventArgs e) { psI.UseShellExecute = false; psI.RedirectStandardInput = true; psI.RedirectStandardOutput = true; psI.RedirectStandardError = true; psI.CreateNoWindow = true; p.StartInfo = psI;
p.Start(); sw = p.StandardInput; sr = p.StandardOutput; err = p.StandardError;
sw.AutoFlush = true;
if (tbCommand.Text != "") { sw.WriteLine(tbCommand.Text); } else { tbResult.Text = "请输入命令"; } sw.Close();
tbResult.Text = "输出结果为:\n" + sr.ReadToEnd().ToString().Replace("\n\n", "\n"); tbResult.Text += "\n=========================================="; tbResult.Text += "\n错误信息:\n" + err.ReadToEnd().ToString(); } }
// 运行结果如下:
(以上程序均在 Microsoft Visual Studio 2005 中调试通过)
|
请发表评论