网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > .Net编程 > 正文

一个C#写的调用外部进程类

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

  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;

  }

  }

  }

  }

  • 下一篇资讯: 谈谈VS中的模板
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师