- 浏览: 245570 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
yulanlian:
...
实现在删除数据后,自增列的值连续 -
RonQi:
楼主写的很好,支持原创!
Google Protocol Buffers
作者:肖波
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; } } } }
发表评论
-
无法破解的软件注册码算法
2011-03-30 19:43 970无法破解的软件注册码算法 实现原代码,包括一个Asp.Net页 ... -
C# 4.0新特性——“协变”与“逆变”以及背后的编程思想
2011-01-16 00:49 8532011-01-14 09:47 | 2265 ... -
【转】把.NET程序部署到没有安装.NET Framwork的机器上
2010-12-04 19:47 1030摘要 本文讨论了如 ... -
c#中的有用的方法
2010-12-04 19:35 1925using System; using System. ... -
实用C#中任意类型数据转成JSON格式数据输出
2010-10-31 17:56 2856下面整理任意类型数据转换成json数据的方法超实用函数: ... -
C#中小数点四舍五入的方法
2010-10-31 17:55 2051下面介绍6种asp.net小数点四舍五入的方法1.只要求保留N ... -
C#中char[]转换成string及string转换成char[]
2010-10-31 17:51 2099C#中char[]与string互相转换的写法: strin ... -
C#调用Exe文件的方法
2010-10-31 17:50 2065很简单的代码就可以实现C#调用EXE文件,如下: 引入usi ... -
解决C#中Thread.Sleep()的作用及用法
2010-10-31 17:45 8122Thread.Sleep 函数来使线程 ... -
C#实现所有经典排序算法(选择排序,冒泡排序,快速排序,插入排序,希尔排序)
2010-10-31 17:45 974C#实现所有经典排序算 ... -
正则表达式整理,C#正则表达式整理备忘
2010-10-31 17:37 863有一段时间,正则表达式学习很火热很潮流,当时在CSDN一天就能 ... -
C# sealed关键字用法
2010-10-31 17:35 931sealed的中文意思是密封,故名思义,就是由它修饰的类或方法 ... -
C#操作系统注册表的方法
2010-10-31 17:34 981Windows 操作系统的注册 ... -
C#多线程中lock的用法
2010-10-31 17:30 847最近在看些c#的代码,发现很多是以前没有接触到了,只能上网查, ... -
C#调用控制台程序并取得输出结果
2010-10-31 17:08 3273Net本身的功能虽然很强 ... -
C#中HashTable的使用方法
2010-10-31 17:05 1256一,哈希表(Hashtable)简述 在.NET Fra ...
相关推荐
总结起来,C#实现异步调用外部程序的关键在于理解和运用`async/await`、`Process`类以及异步等待的策略。通过这种方式,我们可以在不阻塞主线程的情况下执行外部程序,并获取其输出,从而提高应用程序的性能和用户...
【C#调用外部DLL的方法】是C#开发者在处理特定功能或集成其他库时的常见需求。DLL(Dynamic Link Library)是Windows操作系统的核心组成部分,它包含一系列可供不同程序调用的函数或方法。这些函数在需要时由系统...
- 如果外部exe是一个WinForm应用,可以通过反编译工具(如ILSpy或Reflector)查看其窗体类,然后在项目中创建一个对应的窗体类。 2. **调用外部exe作为子窗体** - 使用`System.Diagnostics.Process`类来启动和...
单开一看是外部EXE的界面,我晕,一看这个exe的界面有点吓到我,显示很是蹩脚啊,哈哈,感觉这个仍然不是一个解决办法,后面有继续百度啊,后面发现一些博客里面有一个关于调用一个第三方的Cjwdev.WindowsApi.dll就...
标题所述的"C#_调用外部dll"是指在C#...总结,C#调用外部DLL涉及到对DLL的理解、`DllImport`特性的使用以及可能的数据封送规则。正确配置这些参数,开发者可以灵活地利用各种非托管库的功能,扩大C#应用程序的能力。
在C#编程中,`System.Diagnostics.Process` 类是用于与外部进程交互的重要工具。通过这个类,我们可以启动、控制和管理应用程序,甚至可以执行DOS命令。以下将详细阐述如何利用`Process`类来调用外部程序并执行DOS...
要调用外部程序,我们需要创建`Process`类的一个实例,并设置其`ProcessStartInfo`属性。`ProcessStartInfo`包含了多个用于控制进程启动方式的属性,如`FileName`(程序路径和名称)、`Arguments`(程序参数)等。 ...
2. 创建Process对象:这是调用外部进程的第一步,通过Process类的实例化,我们可以获取或设置与进程相关的属性。 ```csharp Process process = new Process(); ``` 3. 设置进程启动信息:通过ProcessStartInfo对象...
在.NET框架中,有时我们需要对操作系统进行更底层的控制,比如挂起或恢复外部进程的操作。这通常通过调用Windows API来实现,因为.NET Framework的标准库并不直接提供这些功能。本示例主要介绍如何在C#中利用Window...
在C#编程中,关闭外部程序是一个常见的任务,特别是在系统集成、自动化测试或者需要管理其他应用程序的状态时。本文将深入探讨如何使用C#来实现这一功能,并提供相关的知识点。 首先,我们要了解C#中用于与操作系统...
"使用C#8.0中的异步流简化调用外部进程"这个资源包可能包含了如何在C# 8.0中利用异步流优化`Process`类的示例和指导,帮助开发者编写更高效、更易读的代码,同时保持应用的响应性。通过理解异步流的概念以及如何与`...
总的来说,C#调用外部Exe文件的能力使得我们可以灵活地集成各种工具和资源,极大地扩展了应用程序的功能。通过熟练掌握`System.Diagnostics.Process`类的使用,我们可以实现复杂的应用场景,例如自动化测试、数据...
首先,让我们了解C#调用外部exe的基本方法。在C#中,可以使用`System.Diagnostics.Process`类来启动、控制和与外部应用程序交互。以下是一个简单的示例代码: ```csharp using System; using System.Diagnostics; ...
C# 判断并激活外部程序窗口 并实现外部程序窗口最大化,不错的代码与大家分享
在C#编程中,将一个外部的.exe程序嵌入到另一个程序的窗体中,主要涉及到Windows Forms控件和进程管理技术。这个过程通常被称为"嵌入式应用程序"或者"托管应用程序",允许用户在一个主应用程序中直接操作另一个程序...
首先,让我们深入理解C#调用外部程序的方法。在C#中,可以使用`System.Diagnostics.Process`类来启动、控制和与外部应用程序交互。通过创建`Process`对象,设置其`StartInfo`属性,然后调用`Start()`方法,即可启动...
(2)调用外部工具:有些功能无法用 C# 直接实现,但可以通过调用 cmd 执行相应的命令行工具来实现。这样可以充分利用现有的工具和资源,提高开发效率。 (3)灵活性和可扩展性:cmd 提供了丰富的命令和选项,可以...
- 在VS2010中创建一个新的Winform项目,主界面通常会包含一个或多个控件,如按钮(Button)。 - 按钮控件提供了点击事件(Click),我们可以在事件处理函数中编写调用外部程序的代码。 2. **Process类**: - ...
以下是如何使用C#调用外部Ping命令获取网络连接情况的详细步骤: 首先,我们需要引入`System.Diagnostics`命名空间,因为其中包含了`Process`类,它是用于创建和管理进程的关键类。在代码顶部添加`using System....