|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
您现在的位置: ChinaBeta.cn 中文IT资讯 >> 网盟学院 >> 编程类 >> 其它编程程序 >> 网管技术正文
推荐网管技术[多图]即将发布的Microsoft Of…推荐网管技术让我穿过那道"墙"! 畅游网络应…
推荐网管技术文件夹变身磁盘 查看共享有新招…推荐网管技术防患于未然!终截者抗病毒软件…
推荐网管技术主动防御!瑞星杀毒2008抢先评…推荐网管技术玩转虚拟光驱:DAEMON TOOLS P…
推荐网管技术速度超快 Discuz! 6.0.0试用手…推荐网管技术当设计遇上PC:LG XPION A10图…
推荐网管技术奇虎举证:各杀毒软件均报CNNIC…推荐网管技术Google Earth 4.2加入繁体中文…
推荐网管技术Photoshop CS3:蔚蓝梦幻风格婚…推荐网管技术专业防护!瑞星防火墙2008测试…
推荐网管技术挂载RAR文件 从认识到爱上WinM…推荐网管技术让你冲浪随心所欲 如何访问被封…
推荐网管技术轻装上阵!江民杀毒软件2008速…推荐网管技术VMware Fusion苹果版全程图解(…
推荐网管技术VMware Fusion苹果版全程图解(…推荐网管技术从菜鸟出发!征服高清详细评测全…
推荐网管技术VS2008和ASP.NET 3.5使用之初体…推荐网管技术迅雷 快车 电驴 eMule下载飚速…
推荐网管技术[多图]Ubuntu 7.04 初体验推荐网管技术东风吹战鼓擂 下载软件你选谁?
推荐网管技术若隐若现 Windows XP DirectX …推荐网管技术GPRS上网全攻略
推荐网管技术主流杀毒软件Vista兼容性横评推荐网管技术基于IRF的网络管理和业务管理解…
推荐网管技术83个美丽的Wordpress主题推荐网管技术软交换网络中的关键路由技术详…
一个C#写的调用外部进程类
Www.ChinaBeta.Cn 更新时间:2008-4-3

【ChinaBeta.Cn 网盟学院】
  C# 调用外部进程的类,网上可以搜出很多来,为什么要再写一遍,实在是因为最近从网上拷贝了一个简单的例程用到项目中,运行有问题,后来研究了半天,才解决了这些问题。于是打算写这么一篇博文,一来说说调用一个外部进程这么简单的一件事究竟会有哪些问题,二来也希望我写的这个相对比较完整的类可以为软件开发的同道们节约一些脑细胞,以便集中优势兵力解决那些真正高深复杂的软件问题。
    在开始正题之前,我们先来看一看网上比较常见的执行外部进程的函数

 

private string RunCmd(string command)
    {
        //例Process
        Process p = new Process();

        p.StartInfo.FileName = "cmd.exe";           //确定程序名
        p.StartInfo.Arguments = "/c " + command;    //确定程式命令行
        p.StartInfo.UseShellExecute = false;        //Shell的使用
        p.StartInfo.RedirectStandardInput = true;   //重定向输入
        p.StartInfo.RedirectStandardOutput = true; //重定向输出
        p.StartInfo.RedirectStandardError = true;   //重定向输出错误
        p.StartInfo.CreateNoWindow = true;          //设置置不显示示窗口

        p.Start();   //00

        //p.StandardInput.WriteLine(command);       //也可以用这种方式输入入要行的命令
        //p.StandardInput.WriteLine("exit");        //要得加上Exit要不然下一行程式

        return p.StandardOutput.ReadToEnd();        //输出出流取得命令行结果果

    }


    这个方法应该是比较常见的调用外部进程的方法,我以前也一直是这样调用外部进程的,也没有碰到过什么问题。但这次调用的外部进程比较特殊,用这种方法调用就出现了两个问题。

    第一个问题是这个被调用的外部进程有时候会出现异常,出现异常后Windows会弹出错误报告框,程序于是吊死在那里,必须手工干预。这个问题比较好解决,程序中设置一下注册表搞定。

    第二个问题是调用这个外部进程(是一个控制台进程)后,程序会阻塞在p.StandardOutput.ReadToEnd();这一句,永远无法出来,被调用的那个控制台程序也被吊死。但该控制台进程在CMD 中是可以正常执行的。后来看来一些资料才发现原来原因是出在该控制台程序控制台输出大量字符串,管道重定向后,调用程序没有及时将管道中的输出数据取出,结果导致管道被阻塞,程序吊死。在这里还有另外一个问题,虽然这次没有遇到,但网上有其他人遇到,就是错误信息管道不及时取出数据,也会被阻塞,而且如果要同时取出两个管道的数据,必须要利用一个辅助线程才能实现。

    问题讲完了,下面给出这个类的完整代码

 using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;

namespace Laboratory.Process
{
    class ReadErrorThread
    {
        System.Threading.Thread m_Thread;
        System.Diagnostics.Process m_Process;
        String m_Error;
        bool m_HasExisted;
        object m_LockObj = new object();

        public String Error
        {
            get
            {
                return m_Error;
            }
        }

        public bool HasExisted
        {
            get
            {
                lock (m_LockObj)
                {
                    return m_HasExisted;
                }
            }

            set
            {
                lock (m_LockObj)
                {
                    m_HasExisted = value;
                }
            }
        }

        private void ReadError()
        {
            StringBuilder strError = new StringBuilder();
            while (!m_Process.HasExited)
            {
                strError.Append(m_Process.StandardError.ReadLine());
            }

            strError.Append(m_Process.StandardError.ReadToEnd());

            m_Error = strError.ToString();
            HasExisted = true;
        }

        public ReadErrorThread(System.Diagnostics.Process p)
        {
            HasExisted = false;
            m_Error = "";
            m_Process = p;
            m_Thread = new Thread(new ThreadStart(ReadError));
            m_Thread.Start();
        }

    }

    class RunProcess
    {
        private String m_Error;
        private String m_Output;

        public String Error
        {
            get
            {
                return m_Error;
            }
        }

        public String Output
        {
            get
            {
                return m_Output;
            }
        }

        public bool HasError
        {
            get
            {
                return m_Error != "" && m_Error != null;
            }
        }

        public void Run(String fileName, String para)
        {
            StringBuilder outputStr = new StringBuilder();

            try
            {
                //disable the error report dialog.
                //reference: http://www.devcow.com/blogs/adnrg/archive/2006/07/14/Disable-Error-Reporting-Dialog-for-your-application-with-the-registry.aspx
                Microsoft.Win32.RegistryKey key;
                key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"software\microsoft\PCHealth\ErrorReporting\", true);
                int doReport = (int)key.GetValue("DoReport");

                if (doReport != 0)
                {
                    key.SetValue("DoReport", 0);
                }

                int showUI = (int)key.GetValue("ShowUI");
                if (showUI != 0)
                {
                    key.SetValue("ShowUI", 0);
                }
            }
            catch
            {
            }


            m_Error = "";
            m_Output = "";
            try
            {
                System.Diagnostics.Process p = new System.Diagnostics.Process();

                p.StartInfo.FileName = fileName;
                p.StartInfo.Arguments = para;
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardInput = true;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.CreateNoWindow = true;

                p.Start();

                ReadErrorThread readErrorThread = new ReadErrorThread(p);

                while (!p.HasExited)
                {
                    outputStr.Append(p.StandardOutput.ReadLine()+"\r\n");
                }

                outputStr.Append(p.StandardOutput.ReadToEnd());

                while (!readErrorThread.HasExisted)
                {
                    Thread.Sleep(1);
                }

                m_Error = readErrorThread.Error;
                m_Output = outputStr.ToString();
            }
            catch (Exception e)
            {
                m_Error = e.Message;
            }
        }

    }
}

Google

(责任编辑:hahack)

发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
热门文章 相关报道
普通网管技术 [其它编程程序]一个C#写的调用外部进程类 (04-03)最新网管技术
普通网管技术 [其它编程程序]用C#生成不重复的随机数 (04-03)最新网管技术
普通网管技术 [其它编程程序]C#事件(event)解析 (04-03)最新网管技术
普通网管技术 [ASP|ASP.NET]ASP.NET中DataTable对象 (04-03)最新网管技术
普通网管技术 [综合文献]详解Exchange 2007 SP1中统一消息… (04-03)最新网管技术
普通网管技术 [综合文献]扔掉光驱轻松制作系统闪存 (04-03)最新网管技术
普通网管技术 [软件应用]详解IE8新增两项重要安全功能 (04-03)最新网管技术
普通网管技术 [数据库]删除SQL Server 2000数据库危险扩… (04-02)最新网管技术
普通网管技术 [数据库]SQL 2005数据库 转到SQL 2000的步… (04-02)最新网管技术
普通网管技术 [技术文档]Linux - Wine上运行MS Office 20… (04-01)最新网管技术
  • 用C#生成不重复的随机数

  • C#事件(event)解析

  •   网友评论内容:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    I D *
    邮 箱
    主 页
    评 分 1分 2分 3分 4分 5分
    评 论

    关于我们  中国·国家信息产业部{粤ICP备06006652号}{陇ICP备06002562号}
    版权所有:『AK网盟基地』站长:Hahack | QQ:80505955 | E-mail:Hahack@Gmail.com
    Copyright (C) 2005-2007  akhack.org|chinabeta.cn All Rights Reserved