You can run multiple instances of cmd.exe
as detached processes with redirected input and/or output from within a c# program. You cannot, however, create multiple console windows for them straightforwardly and still redirect the input or output back to yourself.
By default, whenever a windows process creates a child process, it inherits the console window of the parent, if any. From Process Creation Flags:
CREATE_NEW_CONSOLE
0x00000010
The new process has a new console, instead of inheriting its parent's console (the default). For more information, see Creation of a Console.
And from Creation of a Console:
The system creates a new console when it starts a console process, a character-mode process whose entry point is the main function. For example, the system creates a new console when it starts the command processor. When the command processor starts a new console process, the user can specify whether the system creates a new console for the new process or whether it inherits the command processor's console.
A process can create a console by using one of the following methods:
- A GUI or console process can use the CreateProcess function with CREATE_NEW_CONSOLE to create a console process with a new console. (By default, a console process inherits its parent's console, and there is no guarantee that input is received by the process for which it was intended.)
- A graphical user interface (GUI) or console process that is not currently attached to a console can use the AllocConsole function to create a new console. (GUI processes are not attached to a console when they are created. Console processes are not attached to a console if they are created using CreateProcess with DETACHED_PROCESS.)
Unfortunately, the Process
class does not expose the CREATE_NEW_CONSOLE
functionality, as can be seen from the reference source.
I will note that your code does successfully create two cmd.exe
processes that, while sharing the same console window, have different input streams and can both be used to execute batch files in parallel. I tested this with the following code, and was able to see multiple instances of cmd.exe
running in the Windows Task Manager, each doing its appointed task:
private static void TestMultipleCmdLaunches()
{
TestCmdLaunch("cmd.exe", GetNextColorCommand(), "title PCRF", "echo window 1", "sleep 60");
TestCmdLaunch("cmd.exe", GetNextColorCommand(), "title PCRF", "echo window 2", "sleep 60");
TestCmdLaunch("cmd.exe", GetNextColorCommand(), "title PCRF", "yes 1");
TestCmdLaunch("cmd.exe", GetNextColorCommand(), "title PCRF", "yes 2");
}
static string[] backgroundColors =
{ "0F","1F","2F","3F","4F", "5F", "60", "70", "8F", "90", "A0", "B0", "C0", "D0", "E0"};
static int lastBackgroundColor = 0;
private static string GetNextColorCommand()
{
int nextColor = unchecked(Interlocked.Increment(ref lastBackgroundColor) % backgroundColors.Length);
return "color " + backgroundColors[nextColor];
}
private static void TestCmdLaunch(string filename, params string [] commands)
{
using (Process p = new Process())
{
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = filename;
info.RedirectStandardInput = true;
info.UseShellExecute = false;
p.StartInfo = info;
p.Start();
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
foreach (var cmd in commands)
{
sw.WriteLine(cmd);
}
}
}
}
}
The only problem is that the outputs appear intermingled in the console window. Perhaps you want to redirect the output back to your own process anyway?