在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 += "\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程序的输出的更多相关文章
- c#中重定向windows控制台程序的输出信息
这个问题来自论坛提问,答案如下.这只是一个简单的ipconfig命令.如果是复杂的,比如oracle的exp之类的命令,能在调用的时候显示出来,还是相当酷的. using System; using ...
- Linux shell编程02 shell程序的执行 及文件权限
第一个shell脚本 1. shell编程的方式 交互式shell编程 非交互式shell编程:执行的语句存放到一个文件 shell脚本:可以任意文件名,建议扩展名为sh 2. ...
- 学习Shell脚本编程(第4期)_在Shell程序中的使用变量
变量的赋值 变量的访问 变量的输入 4.1 变量的赋值 在Shell编程中,所有的变量名都由字符串组成,并且不需要对变量进行声明.要赋值给一个变量,其格式如下: 变量名=值 注意: 等号(= ...
- 学习Shell脚本编程(第3期)_在Shell程序中使用的参数
位置参数 内部参数 如同ls命令可以接受目录等作为它的参数一样,在Shell编程时同样可以使用参数.Shell程序中的参数分为位置参数和内部参数等. 3.1 位置参数 由系统提供的参数称为位置参数.位 ...
- (二)shell中case语句、程序传参、while
2.2.6.1.case语句(1)shell中的case语句和C语言中的switch case语句作用一样,格式有差异(2)shell中的case语句天生没有break,也不需要break,和C语言中 ...
- 4、在Shell程序中的使用变量
学习目标变量的赋值变量的访问变量的输入 12-4-1 变量的赋值在Shell编程中,所有的变量名都由字符串组成,并且不需要对变量进行声明.要赋值给一个变量,其格式如下:变量名=值.注意:等号(=)前后 ...
- 3、在Shell程序中使用的参数
学习目标位置参数内部参数 如同ls命令可以接受目录等作为它的参数一样,在Shell编程时同样可以使用参数.Shell程序中的参数分为位置参数和内部参数等. 12-3-1 位置参数由系统提供的参数称为位 ...
- 工作中一个简单的shell程序
下面是工作中用到的链接数据库的shell程序. #!/bin/bash ] ; then echo "prase is wrong ,please check first" exi ...
- linux shell程序
shell程序介绍 1.查看我们的Linux(centos6.5为例)有多少我们可以使用的shell: [root@localhost bin]# cat /etc/shells /bin/sh /b ...
随机推荐
- mysql case的语法
测试表:team 第一种语法: CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_ ...
- oracle长连接超时设置
方法一.在sqlnet.ora中设置参数 如需要设置客户端空闲10分钟即被中断,则在sqlnet.ora的末尾添加SQLNET.EXPIRE_TIME=10注:sqlnet.ora文件的路径在$ORA ...
- Windos Server 2008 Tomcat 安装
web服务:apache-tomcat-7.0.75环境:jdk-7u80-windows-i586 1.安装jdk环境包 2.配置环境变量--> 环境变量--> 新建W --> 变 ...
- 2017最全的php面试题目及答案总结
最近在网上看到很多的小伙伴们都在询问如何应对php面试,这个对于有工作经验和实战项目的小伙伴来说是没什么问题的,但是对于刚刚学习完php的小伙伴们.php面试却是一个很重要的一步,那么今天php中文网 ...
- 20145222黄亚奇 《网络对抗技术》 MAL_逆向与Bof基础
学习目的 通过一些方法,使能够运行本不该被运行的代码部分,或得到shell的使用: 将正常运行代码部分某处call后的目标地址,修改为另一部分我们希望执行.却本不应该执行的代码部分首地址(这需要我们有 ...
- 数据结构与算法分析:C语言描述(原书第2版 简体中文版!!!) PDF+源代码+习题答案
转自:http://www.linuxidc.com/Linux/2014-04/99735.htm 数据结构与算法分析:C语言描述(原书第2版中文版!!!) PDF+源代码+习题答案 数据结构与算法 ...
- OC_内存管理
引言: 1.OC中的对象都是分配在堆中的 声明对象的格式: Person *person = [Person new ...
- maven项目在打war包时出现非法字符: '\ufeff' 解决方案
问题描述: 开发工具MyEclipse 的总体开发环境,编码格式总体设置为UTF-8,在将web项目打包的时候出现:非法字符:'\ufeff" 错误. 解决方案: 利用notePad++打开 ...
- list!=null跟list.isEmpty()有什么区别?
这就相当与,你要喝水,前面list!=null就是判断是不是连水杯都没有,后面!list.isEmpty就是判断水杯里面没有水,连盛水的东西都没有,这个水从何而来?所以一般的判断是if(list!=n ...
- BZOJ 2752 [HAOI2012]高速公路(road):线段树【维护区间内子串和】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2752 题意: 有一个初始全为0的,长度为n的序列a. 有两种操作: (1)C l r v: ...