C#Windows窗体.Net和DOS控制台

问题描述:

我有一个窗体执行批处理文件。我想将我控制台中发生的所有事情转移到我的表单中的面板。我怎样才能做到这一点?我的DOS控制台如何与我的Windows窗体面板交流?C#Windows窗体.Net和DOS控制台

感谢

你可以调用从窗体应用程序的DOS或批处理程序和输出重定向到一个字符串:

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(); 
} 
+0

你可能想读取从重定向输出流输入前行移动WaitForExit()调用。另外,如果需要,您可以添加WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden标志,以防止控制台应用程序出现,只要它不需要与用户交互即可。 – LBushkin 2009-06-24 20:42:06

+0

谢谢...有没有一种方法可以隐藏OS窗口?它现在正常工作,但显示空的操作系统控制台... – user62958 2009-06-24 22:35:33

我一直在用的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流的调用者读取和写入该流的子进程之间引入依赖关系。这些依赖关系可能导致死锁情况。当调用者从子进程的重定向流中读取时,它依赖于子进程。调用者等待读取操作,直到孩子写入流或关闭流。当子进程写入足够的数据以填充其重定向流时,它依赖于父进程。子进程等待下一个写操作,直到父进程从完整流读取或关闭流。当调用者和子进程等待彼此完成操作并且两者都不能继续时,将导致死锁情况。您可以通过评估调用者和子进程之间的依赖关系来避免死锁。

你应该通过增加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); 

,如果你想呼叫被阻塞(IE,你的应用程序将冻结,直到文件完成),那么只需使用string result = proc.StandardOutput.ReadToEnd()来读取整个批处理文件的输出。

但是,如果您希望应用程序能够继续响应以及实时显示输出,那么您将需要使用BeginOutputReadLine

我敢肯定有更好的选择,但你可以路由命令到一个临时文件

Redirecting Command-Line Output to Files

的输出程序,显示大量 文字,考虑重定向文本 通常显示在标准输出到 文件。显示大量的文字将会减慢执行速度 ;滚动文本 工作站上的终端窗口可能会导致I/O瓶颈(增加 已用时间)并使用更多的CPU时间。

以下命令显示了如何通过 有效地运行 程序更重定向输出到文件中,然后 显示节目输出:从程序

MYPROG> results.lis更results.lis 重定向输出 将更改报告的时间,因为 的屏幕I/O减少。

我想你可以将它路由到一个变量,但不是100%确定。可能有更好的选择,但至少这是一个。

The doc states,如果你想读都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(); 

}