C# 使用 .NET 使用同一进程执行多个命令行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/437419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:22:32  来源:igfitidea点击:

Execute multiple command lines with the same process using .NET

c#.netcommand-line

提问by

I'm trying to execute multiple commands without create a new process each time. Basically, I want to start the DOS command shell, switch to the MySQL command shell, and execute a command. Here's how I am calling the procedure (also below). Also, how do I handle the "\"'s in the command?

我正在尝试执行多个命令而不每次都创建一个新进程。基本上,我想启动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(); }
}

回答by M4N

Couldn't you just write all the commands into a .cmd file in the temp folder and then execute that file?

您不能将所有命令写入临时文件夹中的 .cmd 文件,然后执行该文件吗?

回答by scottm

You can redirect standard input and use a StreamWriter to write to it:

您可以重定向标准输入并使用 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;");
            }
        }

回答by ChrisW

A command-line process such cmd.exeor mysql.exewill usually read (and execute) whatever you (the user) type in (at the keyboard).

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

To mimic that, I think you want to use the RedirectStandardInputproperty: http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardinput.aspx

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

回答by Ben Hoffstein

You could also tell MySQL to execute the commands in the given file, like so:

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

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

回答by Jimmy

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);

The &&is the way to tell the command shell that there is another command to execute.

&&是告诉命令外壳有另一个命令要执行的方法。

回答by Filip

const string strCmdText = "/C command1&command2";
Process.Start("CMD.exe", strCmdText);

回答by Fernando Reis Guimaraes

You need to READ ALL data from input, before send another command!

在发送另一个命令之前,您需要从输入中读取所有数据!

And you can't ask to READ if no data is avaliable... little bit suck isn't?

如果没有可用的数据,你就不能要求阅读……有点糟糕不是吗?

My solutions... when ask to read... ask to read a big buffer... like 1 MEGA...

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

And you will need wait a min 100 milliseconds... sample code...

您将需要等待至少 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

回答by PeterJ

As another answer alludes to under newer versions of Windows it seems to be necessary to read the standard output and/or standard error streams otherwise it will stall between commands. A neater way to do that instead of using delays is to use an async callback to consume output from the stream:

作为另一个答案暗示在较新版本的 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();
}

回答by Hermes Monteiro

I prefer to do it by using a BAT file.

我更喜欢使用 BAT 文件来做到这一点。

With BAT file you have more control and can do whatever you want.

使用 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);