同一进程中的多个CMD命令

时间:2015-09-30 19:22:34

标签: c# cmd

好的,首先是一些背景资料。我编写了一个与cmd.exe进行实时连接的应用程序

问题: 我想写多次而不关闭cmd.exe,而不是一次写入一个进程。这会导致错误,因为我必须在能够检索任何输出之前关闭StreamWriter,并且在我收到输出后,我想再次写入它。

示例:的 我想给出一个命令cd C:\并使用更改的路径接收输出。之后,我想通过dir查看哪些文件位于C:\目录中。 我不希望重新启动进程,因为它会重置路径。

我知道我可以简单地使用dir C:\,但这不是重点。 这只是一个简单的例子,我想将其用于许多其他需要解决此问题的事情。

class Program
    {
        static void Main(string[] args)
        {
            ProcessStartInfo pInfo = new ProcessStartInfo();
            pInfo.RedirectStandardInput = true;
            pInfo.RedirectStandardOutput = true;
            pInfo.RedirectStandardError = true;
            pInfo.UseShellExecute = false;
            pInfo.CreateNoWindow = true;
            pInfo.FileName = "cmd.exe";

            Process p = new Process();
            p.StartInfo = pInfo;

            bool pStarted = false;

            Console.Write("Command: ");
            string command = Console.ReadLine();

            while (command != "exit")
            {
                if (!pStarted && command == "start")
                {
                    p.Start();
                    Console.WriteLine("Process started.");

                    pStarted = true;
                }
                else if (pStarted)
                {
                    StreamWriter sWriter = p.StandardInput;
                    if (sWriter.BaseStream.CanWrite)
                    {
                        sWriter.WriteLine(command);
                    }
                    sWriter.Close();

                    string output = p.StandardOutput.ReadToEnd();
                    string error = p.StandardError.ReadToEnd();

                    Console.WriteLine("\n" + output + "\n");
                }

                Console.Write("\nCommand: ");
                command = Console.ReadLine();
            }

            Console.WriteLine("Process terminated.");
            Console.ReadKey();
            }
    }

每次收到输出时,有没有人知道如何保持进程并多次写入进程。

提前致谢。

修改:这可能与以下问题略有不同:Execute multiple command lines with the same process using .NET。链接的问题没有有用的答案,并且在多个方面有所不同。我面临的一个巨大问题是我希望在用户发送的每个命令之后打印输出。

1 个答案:

答案 0 :(得分:1)

您正在关闭流,但您无法创建新流,因此

  1. 在循环外宣布sWriter
  2. 不要关闭流
  3. 不幸的是,您不能再使用ReadToEnd(),因为这会等到流程终止,cmd没有。因此,你必须

    1. 异步读取控制台输出。
    2. 这再次导致输出问题,因为你的输出"命令:"可能会干扰cmd的输出。

      以下程序的异步版本应解决您的基本问题,但会留下混合输出:

      using System;
      using System.Diagnostics;
      using System.IO;
      
      namespace MultiConsole
      {
          class Program
          {
              private static void Main()
              {
                  var pInfo = new ProcessStartInfo
                  {
                      RedirectStandardInput = true,
                      RedirectStandardOutput = true,
                      RedirectStandardError = true,
                      UseShellExecute = false,
                      CreateNoWindow = false,
                      FileName = "cmd.exe"
                  };
      
                  var p = new Process {StartInfo = pInfo};
      
                  bool pStarted = false;
      
                  Console.Write("Command: ");
                  string command = Console.ReadLine();
                  StreamWriter sWriter = null;
                  while (command != "exit")
                  {
                      if (!pStarted && command == "start")
                      {
                          p.Start();
                          sWriter = p.StandardInput;
                          pStarted = true;
                          ConsumeConsoleOutput(p.StandardOutput);
                          Console.WriteLine("Process started.");
                      }
                      else if (pStarted)
                      {
                          if (sWriter.BaseStream.CanWrite)
                          {
                              sWriter.WriteLine(command);
                          }
                      }
      
                      Console.Write("\nCommand: ");
                      command = Console.ReadLine();
                  }
      
                  if (sWriter != null) sWriter.Close();
                  Console.WriteLine("Process terminated.");
                  Console.ReadKey();
              }
      
              private static async void ConsumeConsoleOutput(TextReader reader)
              {
                  var buffer = new char[1024];
                  int cch;
      
                  while ((cch = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0)
                  {
                      Console.Write(new string(buffer, 0, cch));
                  }
              }
          }
      }