在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 中调试通过)

在C#中实现截获shell程序的输出的更多相关文章

  1. c#中重定向windows控制台程序的输出信息

    这个问题来自论坛提问,答案如下.这只是一个简单的ipconfig命令.如果是复杂的,比如oracle的exp之类的命令,能在调用的时候显示出来,还是相当酷的. using System; using ...

  2. Linux shell编程02 shell程序的执行 及文件权限

    第一个shell脚本 1.       shell编程的方式 交互式shell编程 非交互式shell编程:执行的语句存放到一个文件 shell脚本:可以任意文件名,建议扩展名为sh 2.       ...

  3. 学习Shell脚本编程(第4期)_在Shell程序中的使用变量

    变量的赋值 变量的访问 变量的输入 4.1 变量的赋值     在Shell编程中,所有的变量名都由字符串组成,并且不需要对变量进行声明.要赋值给一个变量,其格式如下: 变量名=值  注意: 等号(= ...

  4. 学习Shell脚本编程(第3期)_在Shell程序中使用的参数

    位置参数 内部参数 如同ls命令可以接受目录等作为它的参数一样,在Shell编程时同样可以使用参数.Shell程序中的参数分为位置参数和内部参数等. 3.1 位置参数 由系统提供的参数称为位置参数.位 ...

  5. (二)shell中case语句、程序传参、while

    2.2.6.1.case语句(1)shell中的case语句和C语言中的switch case语句作用一样,格式有差异(2)shell中的case语句天生没有break,也不需要break,和C语言中 ...

  6. 4、在Shell程序中的使用变量

    学习目标变量的赋值变量的访问变量的输入 12-4-1 变量的赋值在Shell编程中,所有的变量名都由字符串组成,并且不需要对变量进行声明.要赋值给一个变量,其格式如下:变量名=值.注意:等号(=)前后 ...

  7. 3、在Shell程序中使用的参数

    学习目标位置参数内部参数 如同ls命令可以接受目录等作为它的参数一样,在Shell编程时同样可以使用参数.Shell程序中的参数分为位置参数和内部参数等. 12-3-1 位置参数由系统提供的参数称为位 ...

  8. 工作中一个简单的shell程序

    下面是工作中用到的链接数据库的shell程序. #!/bin/bash ] ; then echo "prase is wrong ,please check first" exi ...

  9. linux shell程序

    shell程序介绍 1.查看我们的Linux(centos6.5为例)有多少我们可以使用的shell: [root@localhost bin]# cat /etc/shells /bin/sh /b ...

随机推荐

  1. UNIX 系统常用管理命令

    一. 引言 UNIX系统作为一种强大的多用户分时操作系统,在越来越多的场合受到了应用,同时,对UNIX的系统管理的要求也随之越来越多,但目前的书籍对UNIX系统管理命令介绍的并不是很多.本文主要是针对 ...

  2. 自己动手编译Android源码(超详细)

    http://www.jianshu.com/p/367f0886e62b 在Android Studio代码调试一文中,简单的介绍了代码调试的一些技巧.现在我们来谈谈android源码编译的一些事. ...

  3. 一个可以查询CSS属性兼容性的网站。

    平时遇到CSS属性是不是道理具体兼容哪些网站,就可以直接上这个网站查询啦.http://www.caniuse.com/ 这个是网站地址.  例如查询 inline-block属性兼容性 就可以看到 ...

  4. python:字典的方法

    1.查找字典中的key对应的值和key是否存在(get,has_key)dict.get(key, default = None) :返回字典中key对应的值,若key不存在字典中,则返回defaul ...

  5. PHP的垃圾回收机制以及大概实现

    垃圾回收,简称gc.顾名思义,就是废物重利用的意思.再说这个之前先接触一下内存泄露,大概意思就是申请了一块地儿拉了会儿屎,拉完之后不收拾,那么这块地就算糟蹋了,地越用越少,最后一地全是屎.说到底一句, ...

  6. 一步一步粗谈linux文件系统(三)----超级块(superblock)【转】

    本文转载自:https://blog.csdn.net/fenglifeng1987/article/details/8302921 超级块是来描述整个文件系统信息的,可以说是一个全局的数据结构,可以 ...

  7. nginx根据项目名实现内网地址转发

    nginx根据访问的项目名进行内网地址转发 以下是nginx的配置信息: server { listen 8081; server_name localhost; #charset koi8-r; # ...

  8. CentOS 7(64位) 下Docker的安装

    系统要求是64位,内核版本至少3.10. 首先添加yum软件源: 之后更新yum软件源缓存,并安装docker-engine 查看docker 版本: Cannot connect to the Do ...

  9. Ubuntu 安装mysql

    ubuntu上安装mysql非常简单只需要几条命令就可以完成. 1. sudo apt-get install mysql-server   2. apt-get isntall mysql-clie ...

  10. windows下pip安装包权限的问题

    md哔了狗了,把scipy弄崩了,还顺带把numpy弄崩了... 然后安装包一直权限不允许: 于是按照下面这篇博客以管理员运行cmd,结果还是没卵用 http://www.cnblogs.com/li ...