//实现思想是使用windows api CreatePipe 创建一个匿名管道
//接收控制台命令的输出,并产生委托事件。
//具体实现见以下代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;
namespace Hob.Toolbox
{
    /// <summary>
    /// 重定向的类
    /// </summary>
    public class Redirect : IDisposable
    {
        /// <summary>
        /// 重定向类的代码
        /// </summary>
        public enum RdEventType
        {
            //错误事件
            ErrorEvent,
            //输出事件
            DataEvent,
            //stop事件
            StopEvent
        }
/// <summary>
        /// 事件参数
        /// </summary>
        public struct RdEventArgs
        {
            //code
            public RdEventType eventtype;
            //字符串(错误时代表错误信息,数据时代表数据字符串,stop时代表停止信息)
            public string info;
        };
/// <summary>
        /// 错误处理事件类型
        /// </summary>
        /// <param name="code"></param>
        public delegate void RdEvent(RdEventArgs args);
/// <summary>
        /// 构造函数1
        /// </summary>
        /// <param name="szCommand">命令行</param>
        /// <param name="szCurrentDirectory">当前目录</param>
        public Redirect(string szCommand, string szCurrentDirectory)
        {
            m_szCommand = szCommand;
            m_szCurrentDirectory = szCurrentDirectory;
            m_running = false;
            //默认100毫秒
            m_dwMilliseconds = 100;
            m_processInfo = new PROCESS_INFORMATION();
            m_PipeData = new byte[BUF_SIZE];
            m_readtimer = new System.Windows.Forms.Timer();
            m_readtimer.Enabled = false;
            m_readtimer.Interval = (int)m_dwMilliseconds;
            m_readtimer.Tick += new EventHandler(timertick);
        }
/// <summary>
        /// 构造函数2
        /// </summary>
        /// <param name="szCommand"></param>
        public Redirect(string szCommand)
            :this(szCommand,null)
        {
        }
/// <summary>
        /// 构造函数3
        /// </summary>
        public Redirect()
            :this(null,null)
        {
        }
#region windows api
[StructLayout(LayoutKind.Sequential)]
        class PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public int dwProcessId;
            public int dwThreadId;
        }
[StructLayout(LayoutKind.Sequential)]
        class SECURITY_ATTRIBUTES
        {
            public int nLength;
            public IntPtr lpSecurityDescriptor;
            public int bInheritHandle;
        }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        class STARTUPINFO
        {
            public int cb;
            public string lpReserved;
            public string lpDesktop;
            public string lpTitle;
            public int dwX;
            public int dwY;
            public int dwXSize;
            public int dwYSize;
            public int dwXCountChars;
            public int dwYCountChars;
            public int dwFillAttribute;
            public int dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, SECURITY_ATTRIBUTES lpProcessAttributes,
            SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment,
            string lpCurrentDirectory, STARTUPINFO lpStartupInfo, PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll")]
        static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe,
           SECURITY_ATTRIBUTES lpPipeAttributes, uint nSize);
[DllImport("kernel32.dll", EntryPoint = "PeekNamedPipe", SetLastError = true)]
        static extern bool PeekNamedPipe(IntPtr handle, byte[] buffer, uint nBufferSize, ref uint bytesRead,
                    ref uint bytesAvail, ref uint BytesLeftThisMessage);
[DllImport("kernel32.dll")]
        static extern bool ReadFile(IntPtr hFile, byte[] lpBuffer,
           uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
        static extern Int32 WaitForSingleObject(IntPtr handle, Int32 milliseconds);
[DllImport("kernel32.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)][return: MarshalAs(UnmanagedType.Bool)]
        static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
const int STARTF_USESHOWWINDOW = 0x00000001;
        const int STARTF_USESTDHANDLES = 0x00000100;
        const short SW_HIDE = 0;
        const int WAIT_OBJECT_0 = 0;
#endregion
/// <summary>
        /// 错误报告事件
        /// </summary>
        public event RdEvent RdEventHandler;
private IntPtr m_PipeReadHandle;
        private IntPtr m_PipeWriteHandle;
        private PROCESS_INFORMATION m_processInfo;
        byte[] m_PipeData;
        /// <summary>
        /// buffer的大小
        /// </summary>
        private const int BUF_SIZE = 8192;
/// <summary>
        /// 启动
        /// </summary>
        public void Run()
        {
            //如果已经运行
            if (m_running) return;
SECURITY_ATTRIBUTES SecurityAttributes=new SECURITY_ATTRIBUTES();
            STARTUPINFO StartupInfo=new STARTUPINFO();
            bool Success;
//创建pipe
            SecurityAttributes.nLength = Marshal.SizeOf(SecurityAttributes);
            SecurityAttributes.bInheritHandle = 1;
            SecurityAttributes.lpSecurityDescriptor =IntPtr.Zero;
            Success = CreatePipe(out m_PipeReadHandle, out m_PipeWriteHandle, SecurityAttributes, 0);
            if (!Success)
            {
                RaiseRdEvent(RdEventType.ErrorEvent, "CreatePipe failed.");
                return;
            }
//创建进程
            StartupInfo.cb = Marshal.SizeOf(StartupInfo);
            StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
            StartupInfo.wShowWindow = SW_HIDE;
            StartupInfo.hStdOutput = m_PipeWriteHandle;
            StartupInfo.hStdError = m_PipeWriteHandle;
            Success = CreateProcess(null, m_szCommand, null, null, true, 0, IntPtr.Zero,
                m_szCurrentDirectory, StartupInfo, m_processInfo);
            if (!Success)
            {
                RaiseRdEvent(RdEventType.ErrorEvent, "CreateProcess failed.");
                return;
            }
            //成功,启动时钟周期性的读取管道
            m_running = true;
            m_readtimer.Start();
        }
//触发事件
        private void RaiseRdEvent(RdEventType eventtype,string info)
        {
            RdEventArgs args = new RdEventArgs();
            args.eventtype = eventtype;
            args.info = info;
            if (RdEventHandler != null)
                RdEventHandler(args);
        }
/// <summary>
        /// 时钟触发
        /// </summary>
        /// <param name="state"></param>
        private void timertick(object sender, EventArgs e)
        {
            uint NumBytesRead = 0;
            uint TotalBytesAvailable = 0;
            uint BytesLeftThisMessage = 0;
            //查看数据
            bool Success = PeekNamedPipe(m_PipeReadHandle,m_PipeData,1,ref NumBytesRead,
                ref TotalBytesAvailable,ref BytesLeftThisMessage);
            if(!Success)
            {
                RaiseRdEvent(RdEventType.ErrorEvent, "PeekNamedPipe failed.");
                return;
            }
            //如果读到数据
            if(NumBytesRead>0)
            {
                Success = ReadFile(m_PipeReadHandle,m_PipeData,BUF_SIZE,out NumBytesRead,IntPtr.Zero);
                if(!Success)
                {
                    RaiseRdEvent(RdEventType.ErrorEvent,"ReadFileError failed.");
                    return;
                }
                //处理得到的数据
                dealReadData(m_PipeData, NumBytesRead);
                return;
            }
            //如果没有读到数据,查看进程是否结束了
            if(WaitForSingleObject(m_processInfo.hProcess,0)==WAIT_OBJECT_0)//结束了
            {
                m_running = false;
                RaiseRdEvent(RdEventType.StopEvent, "terminated normal.");
                m_readtimer.Stop();
                FreeHandle();
            }
            //没有结束,do nothing
        }
/// <summary>
        /// 处理得到的数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="num"></param>
        private void dealReadData(byte[] data,uint num)
        {
            Array.Resize(ref data, (int)num);
            //转换为string byte[]中是dbcs,控制台输出的为dbcs字符
            Encoding ec = Encoding.Default;//使用当前系统默认的ansi代码页
            string str = ec.GetString(data);
            //替换'\b' backspace 为空格
            str.Replace('\b', ' ');
            //产生事件
            RaiseRdEvent(RdEventType.DataEvent, str);
        }
/// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            if (!m_running) return;
            //置标志
            m_running = false;
            m_readtimer.Stop();
            //结束进程
            TerminateProcess(m_processInfo.hProcess, 0);
            RaiseRdEvent(RdEventType.StopEvent, "terminated by user.");
            //释放
            FreeHandle();
        }
//释放handle
        private void FreeHandle()
        {
            CloseHandle(m_processInfo.hThread);
            m_processInfo.hThread = IntPtr.Zero;
            CloseHandle(m_processInfo.hProcess);
            m_processInfo.hProcess = IntPtr.Zero;
            CloseHandle(m_PipeReadHandle);
            m_PipeReadHandle = IntPtr.Zero;
            CloseHandle(m_PipeWriteHandle);
            m_PipeWriteHandle = IntPtr.Zero;
        }
/// <summary>
        /// 命令行
        /// </summary>
        private string m_szCommand;
/// <summary>
        /// 当前目录
        /// </summary>
        private string m_szCurrentDirectory;
/// <summary>
        /// 是否工作中
        /// </summary>
        private bool m_running;
/// <summary>
        /// 是否工作中
        /// </summary>
        public bool Running
        {
            get { return m_running; }
        }
/// <summary>
        /// command属性
        /// </summary>
        public string Command
        {
            set
            {
                if (m_running) return;
                m_szCommand = value;
            }
            get { return m_szCommand; }
        }
/// <summary>
        /// 当前目录
        /// </summary>
        public string CurrentDirectory
        {
            set
            {
                if (m_running) return;
                m_szCurrentDirectory = value;
            }
            get { return m_szCurrentDirectory; }
        }
/// <summary>
        /// 读取管道数据的毫秒数
        /// </summary>
        private uint m_dwMilliseconds;
        /// <summary>
        /// 读取时钟,使用windows时钟,避免事件产生在线程中
        /// </summary>
        private System.Windows.Forms.Timer m_readtimer;
/// <summary>
        /// 读取管道数据的毫秒数
        /// </summary>
        public uint ReadMilliseconds
        {
            set
            {
                if (m_running) return;
                m_dwMilliseconds = value;
            }
            get { return m_dwMilliseconds; }
        }
#region Dispose实现
private bool disposed = false;
        public bool IsDisposed
        {
            get { return disposed; }
        }
/// <summary>
        /// 重载dispose,释放非托管资源
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            //do something
            if (!IsDisposed)
            {
                if (disposing){/*free managed resource*/}
                //free unmanaged resource
                Stop();
                m_readtimer.Dispose();
            }
            disposed = true;
        }
public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
// Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~Redirect()     
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }
        #endregion
    }
}

转载于:https://blog.51cto.com/happyoldbear/58552

将控制台输出重定向到textbox的dotnet类相关推荐

  1. 【Java文件操作(八)】将控制台输出重定向到txt文件

    我的博客--Java文件操作系列 [Java文件操作(一)]递归打印文件目录 [Java文件操作(二)]删除文件夹,但保留其内部文件 [Java文件操作(三)]递归复制文件夹内所有文件 [Java文件 ...

  2. java如何在控制台重定向_R - 控制台输出重定向不能(可靠地)从函数调用中工作...

    我编写了以下代码来将控制台输出重定向到文本文件 . 当我以交互方式运行代码时,所有三个命令'(dim,str,summary)输出都会出现在文本文件中 . 但是,当我将代码放在函数中并以交互方式运行函 ...

  3. C# 在自定义的控制台输出重定向类中整合调用方信息

    C# 在自定义的控制台输出重定向类中整合调用方信息 目录 C# 在自定义的控制台输出重定向类中整合调用方信息 一.前言 二.输出重定向基础版 三.输出重定向进阶版(传递调用方信息) 四.后记及资源 独 ...

  4. python控制台输出到文件_Python print 立即打印内容到重定向的文件

    看到本文标题也许要奇怪了,Python 的 print 难道不是也上可以看到结果的吗?在 Python shell 下只要 >> print('Hello world!') Hello w ...

  5. ASP.NET Core 解决控制台输出日志内容前面[40m等乱码字符

    在默认我写了一个 WPF 程序去做管理 ASP.NET Core 进程的日志的时候,重定向输出的内容里面每一行前面都添加了很多乱码字符串.其实这是 ASP.NET Core 控制台的颜色字符,解决方法 ...

  6. python将控制台输出保存至文件

    很多时候在Linux系统下运行python程序时,控制台会输出一些有用的信息.为了方便保存这些信息,有时需要对这些信息进行保存.这里介绍几种将控制台输出保存到文件中的方式: 1 重定向标准输出流 重定 ...

  7. python文件输出-python将控制台输出保存至文件的方法

    很多时候在Linux系统下运行python程序时,控制台会输出一些有用的信息.为了方便保存这些信息,有时需要对这些信息进行保存.这里介绍几种将控制台输出保存到文件中的方式: 1 重定向标准输出流 重定 ...

  8. java生成html 控制编码方式_JAVA中文字符编码问题详解 控制台输出

    JAVA的中文字符乱码问题一直很让人头疼.特别是在WEB应用中.网上的分析文章和解决方案都很多,但总是针对某些特定情况的.很多次遇到乱码问题后, 经过极为辛苦的调试和搜索资料后终于解决,满以为自己已经 ...

  9. linux 输入、输出重定向的概念和用法详解(Day01)

    介绍重定向之前先来介绍几个重要的概念:(笔记不易---- 转载请注明出处) 1.linux 的标准输入与输出  linux标准输入设备指的是键盘,标准输出设备指的是显示器,标准错误输出指的是显示器. ...

最新文章

  1. 【基础】-设置VS2015开发环境
  2. 蓝桥杯2015初赛试题
  3. gitlab linux版本下载,Linux安装GitLab版本控制软件
  4. 智力测试题2——“五个人、五座房子”问题
  5. listActivity和ExpandableListActivity的简单用法
  6. Android之popWindows底部弹出挡住了华为虚拟键盘问题
  7. 2015蓝桥杯省赛---java---A---2(星系炸弹)
  8. 传一个实体一个string_没想到,一个小小的String还有这么多窍门
  9. anaconda cuda路径_anaconda+cuda+cudann+tensorflow环境安装
  10. 埋石图根点lisp代码_GPS测量作业流程.doc
  11. 如果您能天天读上一遍,就能和老外对话了!
  12. JDK1.8后List转Map
  13. java编程比赛_[阶段一]java基础编程比赛
  14. 【windows环境 PKCS11库Demo 用于劫持PKCS11库并打印参数】
  15. 微信小程序全方位深度解析课程Dome-First项目module
  16. python读取文本某一行内容
  17. 桌面文档另存计算机怎么存,如何把word保存到桌面
  18. 三七互娱后端工程师笔试记录
  19. Why So Serious
  20. 如何在visual studio下编译zxing cpp,以及zxing c++的使用

热门文章

  1. AMESim软件建模
  2. java 判断是否包含中文_Java 判断字符串是否包含中文正则表达式
  3. c多线程并发处理方式_Java并发基础,不怕你看不懂
  4. enable pen pressure in ps
  5. Farthest Point Sampling on 2d image
  6. 3.7.4 - Indexing and Slicing Strings
  7. 自注意力机制卷积神经网络的作物叶片病害识别
  8. 编写Java程序,在屏幕上显示带标题的窗口,并添加一个按钮。当用户单击按钮时,结束程序。
  9. java map扩容机制_java中ConcurrentHashMap的扩容机制问题
  10. mysql双活存储容量 TB_Mysql双活方案 - osc_fted3syf的个人空间 - OSCHINA - 中文开源技术交流社区...