【问题标题】:Execute multiple command lines with the same process using .NET使用 .NET 使用同一进程执行多个命令行
【发布时间】:2010-10-01 01:07:25
【问题描述】:

我正在尝试执行多个命令,而不是每次都创建一个新进程。基本上,我想启动 DOS 命令 shell,切换到 MySQL 命令 shell,然后执行一个命令。这是我调用该过程的方式(也在下面)。另外,如何处理命令中的“\”?

ExecuteCommand("mysql --user=root --password=sa casemanager", 100, false);

ExecuteCommand(@"\. " + Environment.CurrentDirectory + @"\MySQL\CaseManager.sql", 100, true);

private void ExecuteCommand(string Command, int Timeout, Boolean closeProcess)
{
    ProcessStartInfo ProcessInfo;
    Process Process;

    ProcessInfo = new ProcessStartInfo("cmd.exe", "/C " + Command);
    ProcessInfo.CreateNoWindow = false;
    ProcessInfo.UseShellExecute = false;
    Process = Process.Start(ProcessInfo);
    Process.WaitForExit(Timeout);

    if (closeProcess == true) { Process.Close(); }
}

【问题讨论】:

    标签: c# .net command-line


    【解决方案1】:

    您可以重定向标准输入并使用 StreamWriter 对其进行写入:

            Process p = new Process();
            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = "cmd.exe";
            info.RedirectStandardInput = true;
            info.UseShellExecute = false;
    
            p.StartInfo = info;
            p.Start();
    
            using (StreamWriter sw = p.StandardInput)
            {
                if (sw.BaseStream.CanWrite)
                {
                    sw.WriteLine("mysql -u root -p");
                    sw.WriteLine("mypassword");
                    sw.WriteLine("use mydb;");
                }
            }
    

    【讨论】:

    • 我已经尝试过了,并且该进程似乎在命令可以通过管道传输到它之前退出。有人可以指出我哪里出错了,或者过去几年的用法发生了变化吗?
    • 对我来说很好。也许这可以标记为答案?
    • 这在企业环境中对我不起作用;我想是因为有一些安全措施阻止了 RedirectStandardInput。使用 && 连接调用 CMD(见下文)虽然有效。
    【解决方案2】:
    const string strCmdText = "/C command1&command2";
    Process.Start("CMD.exe", strCmdText);
    

    【讨论】:

    • 这就是我要找的。 Ot 也适用于特定命令,例如 IF
    【解决方案3】:

    难道你不能把所有的命令都写到 temp 文件夹中的一个 .cmd 文件中,然后执行那个文件吗?

    【讨论】:

    • 不知道为什么这被标记为不是答案,仅仅因为它以问号结尾并不意味着它不是答案=p
    • 我想知道类似的解决方案,但在某些情况下(比如我的)可能包含密码,所以你应该希望在错误的时刻没有崩溃并正确删除文件.. 所以它也会有缺点。
    • 如果您分发的程序包含太多批处理文件,人们也会感到困惑。
    【解决方案4】:

    另一个答案暗示在较新版本的 Windows 下,似乎有必要读取标准输出和/或标准错误流,否则它将在命令之间停止。代替使用延迟的一种更简洁的方法是使用异步回调来消耗流的输出:

    static void RunCommands(List<string> cmds, string workingDirectory = "")
    {
        var process = new Process();
        var psi = new ProcessStartInfo();
        psi.FileName = "cmd.exe";
        psi.RedirectStandardInput = true;
        psi.RedirectStandardOutput = true;
        psi.RedirectStandardError = true;
        psi.UseShellExecute = false;
        psi.WorkingDirectory = workingDirectory;
        process.StartInfo = psi;
        process.Start();
        process.OutputDataReceived += (sender, e) => { Console.WriteLine(e.Data); };
        process.ErrorDataReceived += (sender, e) => { Console.WriteLine(e.Data); };
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();
        using (StreamWriter sw = process.StandardInput)
        {
            foreach (var cmd in cmds)
            {
                sw.WriteLine (cmd);
            }
        }
        process.WaitForExit();
    }
    

    【讨论】:

      【解决方案5】:

      我更喜欢使用 BAT 文件。

      使用 BAT 文件,您拥有更多控制权,可以为所欲为。

      string batFileName = path + @"\" + Guid.NewGuid() + ".bat";
      
      using (StreamWriter batFile = new StreamWriter(batFileName))
      {
          batFile.WriteLine($"YOUR COMMAND");
          batFile.WriteLine($"YOUR COMMAND");
          batFile.WriteLine($"YOUR COMMAND");
      }
      
      ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe", "/c " + batFileName);
      processStartInfo.UseShellExecute = true;
      processStartInfo.CreateNoWindow = true;
      processStartInfo.WindowStyle = ProcessWindowStyle.Normal;
      
      Process p = new Process();
      p.StartInfo = processStartInfo;
      p.Start();
      p.WaitForExit();
      
      File.Delete(batFileName);
      

      【讨论】:

        【解决方案6】:
        ProcessStartInfo pStartInfo = new ProcessStartInfo();
        pStartInfo.FileName = "CMD";
        pStartInfo.Arguments = @"/C mysql --user=root --password=sa casemanager && \. " + Environment.CurrentDirectory + @"\MySQL\CaseManager.sql"
        pStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Process.Start(pStartInfo);
        

        &amp;&amp; 是告诉命令 shell 有另一个命令要执行的方式。

        【讨论】:

        【解决方案7】:

        诸如cmd.exemysql.exe 之类的命令行进程通常会读取(并执行)您(用户)(在键盘上)输入的任何内容。

        为了模仿这一点,我认为您想使用 RedirectStandardInput 属性:http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardinput.aspx

        【讨论】:

        • 非常有用,例如。 G。如果命令可能包含 & 符号。 (我将在其中包含用户输入的文本,因此它们可能包含任何内容,我想我会用上述解决方案将我的 & 符号误解为“新命令”。)
        【解决方案8】:

        您还可以告诉 MySQL 执行给定文件中的命令,如下所示:

        mysql --user=root --password=sa casemanager < CaseManager.sql
        

        【讨论】:

          【解决方案9】:

          您需要从输入读取所有数据,然后再发送另一个命令!

          如果没有可用的数据,你不能要求 READ ......有点糟糕不是吗?

          我的解决方案...当要求阅读时...要求阅读一个大缓冲区...比如 1 MEGA...

          您需要等待至少 100 毫秒...示例代码...

          Public Class Form1
          
              Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
                  Dim oProcess As New Process()
                  Dim oStartInfo As New ProcessStartInfo("cmd.exe", "")
                  oStartInfo.UseShellExecute = False
                  oStartInfo.RedirectStandardOutput = True
                  oStartInfo.RedirectStandardInput = True
                  oStartInfo.CreateNoWindow = True
                  oProcess.StartInfo = oStartInfo
                  oProcess.Start()
          
          
                  Dim Response As String = String.Empty
                  Dim BuffSize As Integer = 1024 * 1024
                  Dim x As Char() = New Char(BuffSize - 1) {}
                  Dim bytesRead As Integer = 0
          
          
                  oProcess.StandardInput.WriteLine("dir")
                  Threading.Thread.Sleep(100)
                  bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)
                  Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))
          
          
          
          
                  MsgBox(Response)
                  Response = String.Empty
          
          
          
          
          
          
                  oProcess.StandardInput.WriteLine("dir c:\")
                  Threading.Thread.Sleep(100)
                  bytesRead = 0
                  bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)
                  Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))
          
                  MsgBox(Response)
          
          
              End Sub
          End Class
          

          【讨论】:

            猜你喜欢
            • 2011-02-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-11-24
            • 2011-01-10
            • 1970-01-01
            • 1970-01-01
            • 2015-08-27
            相关资源
            最近更新 更多