zoukankan      html  css  js  c++  java
  • 在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应用程序

    // 代码如下:
    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 += " 错误信息: "+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 = "输出结果为: " + sr.ReadToEnd().ToString().Replace(" ", " ");
            tbResult.Text += " ==========================================";
            tbResult.Text += " 错误信息: " + err.ReadToEnd().ToString();
        }
    }

    // 运行结果如下:


    (以上程序均在 Microsoft Visual Studio 2005 中调试通过)

  • 相关阅读:
    mac下完全卸载程序的方法
    Mac下检测NSTableView的滑动事件的方法
    一行代码起动全屏
    Unsupported compiler '4.0' selected for architecture 'i386'类错误解决办法
    编译错误“The run destination My Mac 64bit is not valid for Running the scheme '***',解决办法
    ios项目中导入百度地图SDK出错的问题
    Unable to resolve target 'android9'解决办法
    ios保存录制好的视频到相簿的方法
    NSTableView系列之代码创建(不用nib)
    谈内链优化不是每个站点都能做的
  • 原文地址:https://www.cnblogs.com/xumaojun/p/8547401.html
Copyright © 2011-2022 走看看