Execute multiple command lines with the same process using .NET

C#.NetCommand Line

C# Problem Overview


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?

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# Solutions


Solution 1 - C#

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

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

Solution 2 - C#

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

Solution 3 - C#

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

Solution 4 - C#

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:

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

Solution 5 - C#

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.

Solution 6 - C#

I prefer to do it by using a BAT file.

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

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

Solution 7 - C#

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

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

Solution 8 - C#

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

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

Solution 9 - C#

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...

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

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionClintView Question on Stackoverflow
Solution 1 - C#scottmView Answer on Stackoverflow
Solution 2 - C#FilipView Answer on Stackoverflow
Solution 3 - C#M4NView Answer on Stackoverflow
Solution 4 - C#PeterJView Answer on Stackoverflow
Solution 5 - C#JimmyView Answer on Stackoverflow
Solution 6 - C#Hermes MonteiroView Answer on Stackoverflow
Solution 7 - C#ChrisWView Answer on Stackoverflow
Solution 8 - C#Ben HoffsteinView Answer on Stackoverflow
Solution 9 - C#Fernando Reis GuimaraesView Answer on Stackoverflow