天天看點

在C#中實作截獲shell程式的輸出

在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應用程式

在C#中實作截獲shell程式的輸出

// 代碼如下:

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;

    }

}

// 程式運作結果:

在C#中實作截獲shell程式的輸出

// 執行個體二:Asp.net程式

// 執行個體二檔案一:Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" validateRequest="false" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<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.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();

// 運作結果如下:

在C#中實作截獲shell程式的輸出

(以上程式均在 Microsoft Visual Studio 2005 中調試通過)