Reputation: 341
Alright, first some background information. I've written an application to have a real-time connection with the cmd.exe
The problem: Instead of writing once to a Process, I want to write multiple times without closing the cmd.exe. This causes an error because I have to close the StreamWriter before being able to retrieve any output and after I've recieved output, I want to write to it again.
Example:
I want to give a command cd C:\
and recieve the output with the changed path. After that I want to see which files are inside the C:\ directory by using dir
.
I don't want the process to restart, because it resets the path.
I know I can simply use dir C:\
, but that's not the point.
This is only a brief example, I want to use this for many other things that require this problem to be solved.
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();
}
}
Does anyone know how I can hold on to a process and write multiple times to it, each time recieving the output.
Thanks in advance.
Edit : This might or might not be slightly identical to the following question : Execute multiple command lines with the same process using .NET. The question linked has no useful answer and is diffrent in multiple ways. One huge problem I'm facing is that I want the output printed after every command the user sends.
Upvotes: 4
Views: 253
Reputation: 59238
You are closing the stream and you can't simply create a new stream, so
sWriter
outside the loopUnfortunately, you can then not use ReadToEnd()
any more, since that would wait until the process terminates, which cmd
doesn't. Therefore, you have to
This again, results in problems with the output, since your output "Command:" may interfere with the output of cmd
.
The following async version of your program should solve your basic problem, but will leave you with the mixed output:
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));
}
}
}
}
Upvotes: 1