Запустить процесс в текущей консоли
Я пишу базовую оболочку для Windows, и мне было интересно, есть ли способ запустить подпроцесс (Process process
), чтобы он использовал текущее окно консоли. Под этим я подразумеваю, что я не хочу перенаправлять ввод/вывод; Я хочу, чтобы процесс принимал ввод с текущей консоли и печатал вывод непосредственно в том же окне консоли.
Причина в том, что я хочу разрешить этому подпроцессу устанавливать цвета консоли для вывода, чего не может произойти, если я перенаправляю стандартный вывод процесса. Кроме того, я в настоящее время использую код
while (!process.HasExited)
process.StandardInput.WriteLine(Console.ReadLine());
для перенаправления стандартного ввода в процесс. Однако, если процесс выходит сразу после ввода (например, я набираю "exit" + ENTER, и процесс завершается), этот цикл будет запускаться еще раз, поэтому консоль ожидает ввода от пользователя, который никогда не будет использоваться процессом (он должен выйти).
Итак, длинный короткий вопрос, , как я могу запустить процесс в текущей консоли, чтобы он мог устанавливать цвета консоли и напрямую принимать входные данные с консоли?
Изменить: Ниже приведены методы, относящиеся к этому вопросу из моего кода:
static int runExe(string exePath, params string[] args)
{
ProcessStartInfo startInfo = new ProcessStartInfo(exePath, args)
{
ErrorDialog = false,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true
};
Process process = new Process() { StartInfo = startInfo };
process.Start();
ReadThreadState stdout = readThread(process.StandardOutput, false);
ReadThreadState stderr = readThread(process.StandardError, true);
while (!process.HasExited)
process.StandardInput.WriteLine(Console.ReadLine());
stdout.stop = stderr.stop = true;
return process.ExitCode;
}
class ReadThreadState
{
public bool stop;
}
private static ReadThreadState readThread(StreamReader reader, bool isError)
{
ReadThreadState state = new ReadThreadState();
new Thread(() =>
{
while (!state.stop)
{
int current;
while ((current = reader.Read()) >= 0)
if (isError)
writeError(((char)current).ToString(), ConsoleColor.Red);
else
Console.Write((char)current);
}
}).Start();
return state;
}
Ответы
Ответ 1
Вам нужно создать ProcessStartInfo
и установить UseShellExecute
в false
:
var info = new ProcessStartInfo("program.exe", "arguments");
info.UseShellExecute = false;
var proc = Process.Start(info);
proc.WaitForExit();
Это запустит вашу программу в той же консоли.
Рабочая программа, использующая описанную выше технику:
private static void Main(string[] args)
{
Console.WriteLine("Starting program");
var saveColor = Console.BackgroundColor;
Console.BackgroundColor = ConsoleColor.Blue;
var info = new ProcessStartInfo("cmd", "/c time");
info.UseShellExecute = false;
var proc = Process.Start(info);
proc.WaitForExit();
Console.BackgroundColor = saveColor;
Console.WriteLine("Program exited");
Console.ReadLine();
}
Когда вы запускаете программу, она запускает новую копию cmd.exe и запускает команду time, которая запрашивает ввод. Я просто использовал cmd.exe в качестве примера здесь, чтобы проиллюстрировать. Любая программа, которая читает со стандартного ввода, будет работать. Также обратите внимание, что цвета консоли работают правильно.
Ответ 2
Ответ Джима Мишеля работает как шарм. Я перемещаю обработку пакетных файлов на С#, и это отлично работает. Вы можете найти этот небольшой метод полезности. Просто берет командную строку и запускает ее так же, как CALL в пакетном файле. Просто введите его в класс утилиты:
public static void RunCmd(string command) {
Process.Start(new ProcessStartInfo("cmd.exe", "/c " + command) {
UseShellExecute = false
}).WaitForExit();
}