谢谢
using (var p = new System.Diagnostics.Process( ))
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = PathToBatchFile;
p.StartInfo.Arguments = args;
p.Start( );
string o = p.StandardOutput.ReadToEnd( );
p.WaitForExit( );
}
文档指出,如果您想要读取StandardError和StandardOutput,您需要异步读取它们中的至少一个,以避免死锁。
此外,如果您在重定向的流之一上调用ReadToEnd,则必须在调用WaitForExit()之前这样做。如果在调用ReadToEnd之前调用WaitForExit,则输出缓冲区可能会填满,挂起进程,这意味着它将永远不会退出。那将是一个非常漫长的等待时间。这也在文档中有说明!
示例:
string output;
string error;
System.Diagnostics.Process p = new System.Diagnostics.Process
{
StartInfo =
{
FileName = program,
Arguments = args,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
UseShellExecute = false,
}
};
if (waitForExit)
{
StringBuilder sb = new StringBuilder();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
Action<Object,DataReceivedEventArgs> stdErrorRead = (o,e) =>
{
if (!String.IsNullOrEmpty(e.Data))
sb.Append(e.Data);
};
p.ErrorDataReceived += stdErrorRead;
p.Start();
// begin reading stderr asynchronously
p.BeginErrorReadLine();
// read stdout synchronously
output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
// return code is in p.ExitCode
if (sb.Length > 0)
error= sb.ToString();
}
您应该首先添加对 System.Diagnostics
的引用,然后像这样调用批处理文件:
string myFile = "c:\\path\\to\\batch_file.bat";
ProcessStartInfo psi = new ProcessStartInfo(myFile);
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
Process proc = Process.Start(psi);
string result = proc.StandardOutput.ReadToEnd()
来读取批处理文件输出的所有内容。我一直在尝试使用System.Diagnostics.Process类来调用基于控制台的应用程序,并格式化并返回输出。我认为它也可以用于批处理文件。我会花点时间在这里进行测试。以下是一些示例代码:
System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo();
start.UseShellExecute = false;
start.RedirectStandardInput = true;
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
start.RedirectStandardOutput = true;
start.FileName = "at";
System.Diagnostics.Process myP = System.Diagnostics.Process.Start(start);
String strOutput = myP.StandardOutput.ReadToEnd();
if (strOutput.Contains("There are no entries in the list."))
{
litMsg.Text = "There are no jobs";
}
else
{
strOutput = strOutput.Replace("\r", "");
foreach (String line in strOutput.Split("\n".ToCharArray()))
{
//(0,7) (7,5)(12, 24) (36, 14) (50, )
//Status ID Day Time Command Line
//-------------------------------------------------------------------------------
// 1 Tomorrow 3:00 AM dir *
if (line.Length > 50)
{
String Status = line.Substring(0, 7);
String ID = line.Substring(7, 5);
String Day = line.Substring(12, 24);
String Time = line.Substring(35, 14);
String Command = line.Substring(49);
}
}
}
最近我开发了一个小应用程序,其中涉及到批处理文件的交互。我找到了下面这段代码片段,使我能够实现这个功能:
Process proc = new Process
{
StartInfo =
{
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
}
};
proc.Start();
string errorMessage = proc.StandardError.ReadToEnd();
proc.WaitForExit();
string outputMessage = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
从这里开始,只需将这些字符串直接传递到您选择的用户控件中即可。
编辑
注意:这不是一个通用解决方案。它可能导致死锁。根据RedirectStandardError的文档:
同步读操作在调用者从StandardError流中读取和子进程写入该流之间引入了依赖关系。这些依赖关系可能导致死锁条件。当调用者从子进程的重定向流中读取时,它依赖于子进程。调用者等待读操作,直到子进程写入流或关闭流。当子进程写入足够填充其重定向流的数据时,它依赖于父进程。子进程等待下一次写操作,直到父进程从完整的流中读取或关闭流。当调用者和子进程互相等待对方完成操作,而双方都无法继续时,就会发生死锁条件。您可以通过评估调用者和子进程之间的依赖关系来避免死锁。
我相信有更好的选择,但您可以将命令的输出路由到临时文件。
对于显示大量文本的程序,请考虑将通常显示在stdout上的文本重定向到文件中。 显示大量文本会减慢执行速度; 在工作站上滚动文本可能会导致I / O瓶颈(增加的经过时间)并使用更多CPU时间。
以下命令显示如何通过将输出重定向到文件,然后显示程序输出来更有效地运行程序:
myprog > results.lis more results.lis 从程序重定向输出将更改报告的时间,因为屏幕I / O减少了。
我认为您也可以将其路由到变量中,但不确定。 可能有更好的选择,但至少这是其中之一。