熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

一個C#寫的調用外部進程類

2013-11-13 12:20:01  來源: .NET編程 

    C# 調用外部進程的類網上可以搜出很多來為什麼要再寫一遍實在是因為最近從網上拷貝了一個簡單的例程用到項目中運行有問題後來研究了半天才解決了這些問題於是打算寫這麼一篇博文一來說說調用一個外部進程這麼簡單的一件事究竟會有哪些問題二來也希望我寫的這個相對比較完整的類可以為軟件開發的同道們節約一些腦細胞以便集中優勢兵力解決那些真正高深復雜的軟件問題
    在開始正題之前我們先來看一看網上比較常見的執行外部進程的函數

 

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

        pStartInfoFileName = cmdexe;           //確定程序名
        pStartInfoArguments = /c + command;    //確定程式命令行
        pStartInfoUseShellExecute = false;        //Shell的使用
        pStartInfoRedirectStandardInput = true;   //重定向輸入
        pStartInfoRedirectStandardOutput = true;  //重定向輸出
        pStartInfoRedirectStandardError = true;   //重定向輸出錯誤
        pStartInfoCreateNoWindow = true;          //設置置不顯示窗口
        pStart();   //
        //pStandardInputWriteLine(command);       //也可以用這種方式輸入命令
        //pStandardInputWriteLine(exit);        //要得加上Exit
        return pStandardOutputReadToEnd();        //輸出出流取得命令行結果

    }


    這個方法應該是比較常見的調用外部進程的方法我以前也一直是這樣調用外部進程的也沒有碰到過什麼問題但這次調用的外部進程比較特殊用這種方法調用就出現了兩個問題

    第一個問題是這個被調用的外部進程有時候會出現異常出現異常後Windows會彈出錯誤報告框程序於是吊死在那裡必須手工干預這個問題比較好解決程序中設置一下注冊表搞定

    第二個問題是調用這個外部進程(是一個控制台進程)後程序會阻塞在pStandardOutputReadToEnd()這一句永遠無法出來被調用的那個控制台程序也被吊死但該控制台進程在CMD 中是可以正常執行的後來看來一些資料才發現原來原因是出在該控制台程序控制台輸出大量字符串管道重定向後調用程序沒有及時將管道中的輸出數據取出結果導致管道被阻塞程序吊死在這裡還有另外一個問題雖然這次沒有遇到但網上有其他人遇到就是錯誤信息管道不及時取出數據也會被阻塞而且如果要同時取出兩個管道的數據必須要利用一個輔助線程才能實現

    問題講完了下面給出這個類的完整代碼

    using System;
    using SystemCollectionsGeneric;
    using SystemText;
    using SystemRuntimeInteropServices;
    using SystemThreading;
    namespace LaboratoryProcess
    {
    class ReadErrorThread
    {
        SystemThreadingThread m_Thread;
        SystemDiagnosticsProcess 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_ProcessHasExited)
            {
                strErrorAppend(m_ProcessStandardErrorReadLine());
            }
            strErrorAppend(m_ProcessStandardErrorReadToEnd());

            m_Error = strErrorToString();
            HasExisted = true;
        }
        public ReadErrorThread(SystemDiagnosticsProcess p)
        {
            HasExisted = false;
            m_Error = ;
            m_Process = p;
            m_Thread = new Thread(new ThreadStart(ReadError));
            m_ThreadStart();
        }

    }
    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://wwwdevcowcom/blogs/adnrg/archive////DisableErrorReportingDialogforyourapplicationwiththeregistryaspx
                MicrosoftWinRegistryKey key;
                key = MicrosoftWinRegistryLocalMachineOpenSubKey(@software\microsoft\PCHealth\ErrorReporting\ true);
                int doReport = (int)keyGetValue(DoReport);
                if (doReport != )
                {
                    keySetValue(DoReport );
                }
                int showUI = (int)keyGetValue(ShowUI);
                if (showUI != )
                {
                    keySetValue(ShowUI );
                }
            }
            catch
            {
            }
            m_Error = ;
            m_Output = ;
            try
            {
                SystemDiagnosticsProcess p = new SystemDiagnosticsProcess();
                pStartInfoFileName = fileName;
                pStartInfoArguments = para;
                pStartInfoUseShellExecute = false;
                pStartInfoRedirectStandardInput = true;
                pStartInfoRedirectStandardOutput = true;
                pStartInfoRedirectStandardError = true;
                pStartInfoCreateNoWindow = true;
                pStart();
                ReadErrorThread readErrorThread = new ReadErrorThread(p);

                while (!pHasExited)
                {
                    outputStrAppend(pStandardOutputReadLine()+\r\n);
                }
                outputStrAppend(pStandardOutputReadToEnd());
                while (!readErrorThreadHasExisted)
                {
                    ThreadSleep();
                }
                m_Error = readErrorThreadError;
                m_Output = outputStrToString();
            }
            catch (Exception e)
            {
                m_Error = eMessage;
            }
        }

    }
    }


From:http://tw.wingwit.com/Article/program/net/201311/15678.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.